您好,登錄后才能下訂單哦!
Java 8日期與數據庫日期的映射關系是什么,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
Java8中有很多新型的日期類型,比傳統的日期類型好用。使用什么和數據庫的日期進行映射,卻是一個比較復雜的問題。
根據JDBC4.2的規范,Java日期類型和數據庫日期類型關系如下:
Java 日期 | 數據庫日期 |
---|---|
java.sql.Date | DATE |
java.sql.Time | TIME |
java.sql.Timestamp | TIMESTAMP |
java.util.Calendar | TIMESTAMP |
java.util.Date | TIMESTAMP |
java.time.LocalDate | DATE |
java.time.LocalTime | TIME |
java.time.LocalDateTime | TIMESTAMP |
java.time.OffsetTime | TIME_WITH_TIMEZONE |
java.time.OffsetDatetime | TIMESTAMP_WITH_TIMEZONE |
有兩個是比較特別的。
TIMESTAMP_WITH_TIMEZONE:包含 Time Zone 的日期時間(DateTime),映射為OffsetDatetime。
TIME_WITH_TIMEZONE:包含 Time Zone 的時間(Time),映射為OffsetTime。
java8中新的日期類型代替舊日期類型
java.time.LocalDate代替java.sql.Date
java.time.LocalTime代替java.sql.Time
java.time.LocalDateTime代替java.sql.Timestamp
注意:JDBC4.2規范不支持Instant和ZonedOffsetDateTime
Java 日期 | 數據庫日期 |
---|---|
java.time.LocalDate | DATE |
java.time.LocalTime | TIME[ WITHOUT TIME ZONE ] |
java.time.LocalDateTime | TIMESTAMP [ WITHOUT TIME ZONE ] |
java.time.OffsetDatetime | TIMESTAMP WITH TIME ZONE |
除了不支持Instant和ZonedOffsetDateTime外,OffsetTime也不支持。
參考:PostgreSQL JDBC: Using Java 8 Date and Time classes
timestamp類似LocalDateTime,只是本地時間。要確保JVM的時區和數據庫的時區一致,否則會出現時差。
timestamptz是TIMESTAMP WITH TIME ZONE類型,但并沒有保存 Time Zone 信息,只是簡單的使用UTC標準時間。理由是Time Zone只用于顯示,而如何顯示時間應該由應用程序處理,沒有必要保存到數據庫中。
MySQL甚至沒有提供TIMESTAMP WITH TIME ZONE的類型,日期時間類型只有DateTime,沒有 Time Zone 概念。必須使用jdbc連接中的serverTimezone確定時區。如jdbc:mysql://localhost/ujcms?serverTimezone=Asia/Shanghai。
Date:本地時間。精度到秒。
Timestamp:本地時間。精度可以到納秒。
TIMESTAMP WITH TIME ZONE:標準的OffsetDateTime,保存有Time Zone 信息。
TIMESTAMP WITH LOCAL TIME ZONE:和PostgresSQL的timestamptz類似,只保存標準的UTC時間,然后根據本地的 Time Zone 進行計算。
datetime2:本地時間。
datetimeoffset:標準的OffsetDateTime,保存有 Time Zone 信息。
JPA對日期的支持于JDBC規范是一致的。
Hibernate在JPA的基礎上進行了擴展,支持Instant、ZonedDateTime。
但所有的Java8日期類型最后都轉換成Timestamp進行處理。也就是說即使數據庫支持TIMESTAMP WITH TIME ZONE并保存了時區信息,Hibernate也會將其丟棄,轉而使用JVM的時區(時間是確保正確的)。
支持Instant。轉為Timestamp處理。
支持ZonedDateTime,直接使用原生的。兼容性差,如PostgreSQL JDBC不支持這種類型的,會報錯。
使用freemarker-java-8進行格式化。
支持OffsetDateTime和ZonedDateTime的格式化,使用對象中自帶的時區。
不支持Instant格式化,會直接調用toString()方法。官方說會增加Instant的支持,但已經3年沒有發布新版本。
支持OffsetDateTime和ZonedDateTime的格式化,使用對象中自帶的時區。
支持Instant格式化,使用JVM默認時區。
Instant:2008-08-08T08:00:00Z
OffsetDateTime:與Instant一致。
ZondDateTime:2008-08-08T08:00:00Z[UTC]
LocalDateTime雖然日期顯示友好,但時區不確定,取決于JVM的時區。這導致時間也不確定,不同時區的JVM訪問數據庫,會得到不一樣的時間。這非常致命,使用LocalDateTime一定要確保JVM和數據庫的時區一致。
按照JDBC規范,毫無疑問應該選擇OffsetDateTime。OffsetDateTime是一個好選擇,具有像LocalDateTime一樣直觀友好的日期顯示,又能確保時間的確定性。
但由于MySQL和PostgreSQL都沒有提供真正的保存時區的TIMESTAMP WITH TIME ZONE,OffsetDateTime其實已經降級為Instant(PostgresSQL的timestamptz本質上就是Instant)。特別是PostgreSQL提供的是一個標準UTC時區,而實際需要的是UTC+8的北京時間,這導致在Freemarker和Thymeleaf中都無法得到正確的格式化。
考慮到數據庫兼容性的問題,Instant似乎是一個更好的選擇。但JDBC4.2及JDBC4.3都不支持Instant,且Instant在Freemarker中也無法格式化。
大部分數據庫都提供真正的TIMESTAMP WITH TIME ZONE,即使是MySQL也能通過設置serverTimezone得到時區正確的OffsetDateTime,再加上JDBC規范的要求,OffsetDateTime還是首選。至于PostgreSQL的兼容性,可以在FreeMarker和Thymeleaf中自定義日期格式化方法。
Java是一門面向對象編程語言,可以編寫桌面應用程序、Web應用程序、分布式系統和嵌入式系統應用程序。
看完上述內容,你們掌握Java 8日期與數據庫日期的映射關系是什么的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。