温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java 8日期与数据库日期的映射关系是什么

发布时间:2022-01-19 15:58:27 来源:亿速云 阅读:313 作者:kk 栏目:开发技术

Java 8日期与数据库日期的映射关系是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

Java8中有很多新型的日期类型,比传统的日期类型好用。使用什么和数据库的日期进行映射,却是一个比较复杂的问题。

JDBC 4.2 规范

根据JDBC4.2的规范,Java日期类型和数据库日期类型关系如下:

Java 日期数据库日期
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

有两个是比较特别的。

  • 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

PostgreSQL JDBC 实现

Java 日期数据库日期
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 数据库

timestamp类似LocalDateTime,只是本地时间。要确保JVM的时区和数据库的时区一致,否则会出现时差。

timestamptz是TIMESTAMP WITH TIME ZONE类型,但并没有保存 Time Zone 信息,只是简单的使用UTC标准时间。理由是Time Zone只用于显示,而如何显示时间应该由应用程序处理,没有必要保存到数据库中。

mysql-">MySQL 数据库

MySQL甚至没有提供TIMESTAMP WITH TIME ZONE的类型,日期时间类型只有DateTime,没有 Time Zone 概念。必须使用jdbc连接中的serverTimezone确定时区。如jdbc:mysql://localhost/ujcms?serverTimezone=Asia/Shanghai。

Oracle 数据库

Date:本地时间。精度到秒。
Timestamp:本地时间。精度可以到纳秒。
TIMESTAMP WITH TIME ZONE:标准的OffsetDateTime,保存有Time Zone 信息。
TIMESTAMP WITH LOCAL TIME ZONE:和PostgresSQL的timestamptz类似,只保存标准的UTC时间,然后根据本地的 Time Zone 进行计算。

SQL Server 数据库

datetime2:本地时间。
datetimeoffset:标准的OffsetDateTime,保存有 Time Zone 信息。

JPA

JPA对日期的支持于JDBC规范是一致的。

Hibernate

Hibernate在JPA的基础上进行了扩展,支持Instant、ZonedDateTime。

但所有的Java8日期类型最后都转换成Timestamp进行处理。也就是说即使数据库支持TIMESTAMP WITH TIME ZONE并保存了时区信息,Hibernate也会将其丢弃,转而使用JVM的时区(时间是确保正确的)。

MyBatis

支持Instant。转为Timestamp处理。

支持ZonedDateTime,直接使用原生的。兼容性差,如PostgreSQL JDBC不支持这种类型的,会报错。

Freemarker

使用freemarker-java-8进行格式化。

支持OffsetDateTime和ZonedDateTime的格式化,使用对象中自带的时区。

不支持Instant格式化,会直接调用toString()方法。官方说会增加Instant的支持,但已经3年没有发布新版本。

Thymeleaf

支持OffsetDateTime和ZonedDateTime的格式化,使用对象中自带的时区。

支持Instant格式化,使用JVM默认时区。

Jackson

  • 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是什么

Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序。

看完上述内容,你们掌握Java 8日期与数据库日期的映射关系是什么的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI