溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java 8日期與數(shù)據(jù)庫(kù)日期的映射關(guān)系是什么

發(fā)布時(shí)間:2022-01-19 15:58:27 來(lái)源:億速云 閱讀:299 作者:kk 欄目:開(kāi)發(fā)技術(shù)

Java 8日期與數(shù)據(jù)庫(kù)日期的映射關(guān)系是什么,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

Java8中有很多新型的日期類型,比傳統(tǒng)的日期類型好用。使用什么和數(shù)據(jù)庫(kù)的日期進(jìn)行映射,卻是一個(gè)比較復(fù)雜的問(wèn)題。

JDBC 4.2 規(guī)范

根據(jù)JDBC4.2的規(guī)范,Java日期類型和數(shù)據(jù)庫(kù)日期類型關(guān)系如下:

Java 日期數(shù)據(jù)庫(kù)日期
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP
java.util.CalendarTIMESTAMP
java.util.DateTIMESTAMP
java.time.LocalDateDATE
java.time.LocalTimeTIME
java.time.LocalDateTimeTIMESTAMP
java.time.OffsetTimeTIME_WITH_TIMEZONE
java.time.OffsetDatetimeTIMESTAMP_WITH_TIMEZONE

有兩個(gè)是比較特別的。

  • TIMESTAMP_WITH_TIMEZONE:包含 Time Zone 的日期時(shí)間(DateTime),映射為OffsetDatetime。

  • TIME_WITH_TIMEZONE:包含 Time Zone 的時(shí)間(Time),映射為OffsetTime。

java8中新的日期類型代替舊日期類型

  • java.time.LocalDate代替java.sql.Date

  • java.time.LocalTime代替java.sql.Time

  • java.time.LocalDateTime代替java.sql.Timestamp

注意:JDBC4.2規(guī)范不支持Instant和ZonedOffsetDateTime

PostgreSQL JDBC 實(shí)現(xiàn)

Java 日期數(shù)據(jù)庫(kù)日期
java.time.LocalDateDATE
java.time.LocalTimeTIME[ WITHOUT TIME ZONE ]
java.time.LocalDateTimeTIMESTAMP [ WITHOUT TIME ZONE ]
java.time.OffsetDatetimeTIMESTAMP WITH TIME ZONE

除了不支持Instant和ZonedOffsetDateTime外,OffsetTime也不支持。

參考:PostgreSQL JDBC: Using Java 8 Date and Time classes

PostgreSQL 數(shù)據(jù)庫(kù)

timestamp類似LocalDateTime,只是本地時(shí)間。要確保JVM的時(shí)區(qū)和數(shù)據(jù)庫(kù)的時(shí)區(qū)一致,否則會(huì)出現(xiàn)時(shí)差。

timestamptz是TIMESTAMP WITH TIME ZONE類型,但并沒(méi)有保存 Time Zone 信息,只是簡(jiǎn)單的使用UTC標(biāo)準(zhǔn)時(shí)間。理由是Time Zone只用于顯示,而如何顯示時(shí)間應(yīng)該由應(yīng)用程序處理,沒(méi)有必要保存到數(shù)據(jù)庫(kù)中。

mysql-">MySQL 數(shù)據(jù)庫(kù)

MySQL甚至沒(méi)有提供TIMESTAMP WITH TIME ZONE的類型,日期時(shí)間類型只有DateTime,沒(méi)有 Time Zone 概念。必須使用jdbc連接中的serverTimezone確定時(shí)區(qū)。如jdbc:mysql://localhost/ujcms?serverTimezone=Asia/Shanghai。

Oracle 數(shù)據(jù)庫(kù)

Date:本地時(shí)間。精度到秒。
Timestamp:本地時(shí)間。精度可以到納秒。
TIMESTAMP WITH TIME ZONE:標(biāo)準(zhǔn)的OffsetDateTime,保存有Time Zone 信息。
TIMESTAMP WITH LOCAL TIME ZONE:和PostgresSQL的timestamptz類似,只保存標(biāo)準(zhǔn)的UTC時(shí)間,然后根據(jù)本地的 Time Zone 進(jìn)行計(jì)算。

SQL Server 數(shù)據(jù)庫(kù)

datetime2:本地時(shí)間。
datetimeoffset:標(biāo)準(zhǔn)的OffsetDateTime,保存有 Time Zone 信息。

JPA

JPA對(duì)日期的支持于JDBC規(guī)范是一致的。

Hibernate

Hibernate在JPA的基礎(chǔ)上進(jìn)行了擴(kuò)展,支持Instant、ZonedDateTime。

但所有的Java8日期類型最后都轉(zhuǎn)換成Timestamp進(jìn)行處理。也就是說(shuō)即使數(shù)據(jù)庫(kù)支持TIMESTAMP WITH TIME ZONE并保存了時(shí)區(qū)信息,Hibernate也會(huì)將其丟棄,轉(zhuǎn)而使用JVM的時(shí)區(qū)(時(shí)間是確保正確的)。

MyBatis

支持Instant。轉(zhuǎn)為T(mén)imestamp處理。

支持ZonedDateTime,直接使用原生的。兼容性差,如PostgreSQL JDBC不支持這種類型的,會(huì)報(bào)錯(cuò)。

Freemarker

使用freemarker-java-8進(jìn)行格式化。

支持OffsetDateTime和ZonedDateTime的格式化,使用對(duì)象中自帶的時(shí)區(qū)。

不支持Instant格式化,會(huì)直接調(diào)用toString()方法。官方說(shuō)會(huì)增加Instant的支持,但已經(jīng)3年沒(méi)有發(fā)布新版本。

Thymeleaf

支持OffsetDateTime和ZonedDateTime的格式化,使用對(duì)象中自帶的時(shí)區(qū)。

支持Instant格式化,使用JVM默認(rèn)時(shí)區(qū)。

Jackson

  • Instant:2008-08-08T08:00:00Z

  • OffsetDateTime:與Instant一致。

  • ZondDateTime:2008-08-08T08:00:00Z[UTC]

如何選擇

LocalDateTime雖然日期顯示友好,但時(shí)區(qū)不確定,取決于JVM的時(shí)區(qū)。這導(dǎo)致時(shí)間也不確定,不同時(shí)區(qū)的JVM訪問(wèn)數(shù)據(jù)庫(kù),會(huì)得到不一樣的時(shí)間。這非常致命,使用LocalDateTime一定要確保JVM和數(shù)據(jù)庫(kù)的時(shí)區(qū)一致。

按照J(rèn)DBC規(guī)范,毫無(wú)疑問(wèn)應(yīng)該選擇OffsetDateTime。OffsetDateTime是一個(gè)好選擇,具有像LocalDateTime一樣直觀友好的日期顯示,又能確保時(shí)間的確定性。

但由于MySQL和PostgreSQL都沒(méi)有提供真正的保存時(shí)區(qū)的TIMESTAMP WITH TIME ZONE,OffsetDateTime其實(shí)已經(jīng)降級(jí)為Instant(PostgresSQL的timestamptz本質(zhì)上就是Instant)。特別是PostgreSQL提供的是一個(gè)標(biāo)準(zhǔn)UTC時(shí)區(qū),而實(shí)際需要的是UTC+8的北京時(shí)間,這導(dǎo)致在Freemarker和Thymeleaf中都無(wú)法得到正確的格式化。

考慮到數(shù)據(jù)庫(kù)兼容性的問(wèn)題,Instant似乎是一個(gè)更好的選擇。但JDBC4.2及JDBC4.3都不支持Instant,且Instant在Freemarker中也無(wú)法格式化。

大部分?jǐn)?shù)據(jù)庫(kù)都提供真正的TIMESTAMP WITH TIME ZONE,即使是MySQL也能通過(guò)設(shè)置serverTimezone得到時(shí)區(qū)正確的OffsetDateTime,再加上JDBC規(guī)范的要求,OffsetDateTime還是首選。至于PostgreSQL的兼容性,可以在FreeMarker和Thymeleaf中自定義日期格式化方法。

Java是什么

Java是一門(mén)面向?qū)ο缶幊陶Z(yǔ)言,可以編寫(xiě)桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序。

看完上述內(nèi)容,你們掌握J(rèn)ava 8日期與數(shù)據(jù)庫(kù)日期的映射關(guān)系是什么的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI