Hibernate与Java 8 LocalDate&数据库中的LocalDateTime [英] Hibernate with Java 8 LocalDate & LocalDateTime in Database

查看:195
本文介绍了Hibernate与Java 8 LocalDate&数据库中的LocalDateTime的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的要求是要存储一个隐含的/直接的答案,但不知何故,我无法将其包围。所有日期&数据库中UTC时区的日期时间。我正在使用Java 8的 LocalDate & LocalDateTime 在我的Hibernate实体中。

正确的是 LocalDate & LocalDateTime 没有与它们关联的时区?



如果不是,我应该回退到使用旧的或遗产?)日期& 时间戳

或者我应该使用Java 8的 Instant ?如果使用即时,那么是否有可能只存储日期部分,而没有时间?

如果它使任何不同之处,我希望他们工作的数据库是MySQL& SQL Server。



同样,如果它有更大的区别,那么它就是Spring Boot应用程序。



谢谢!!

解决方案

Local ...类型故意没有时区概念。所以他们不会表示时间轴上的某一刻。一个 LocalDateTime 表示可能时刻的模糊范围,但在分配偏移或时区之前没有真正意义。这意味着应用 ZoneId 来获取 ZonedDateTime 。例如,说今年圣诞节从12月25日的第一天开始,我们说:

  LocalDateTime ldt = LocalDateTime.of(2017,12,25,0,0,0,0); 

但午夜的那次中风发生在东部比西部早。



这就是为什么精灵的后勤部门从。在那里交付后,他们将圣诞老人西向路线发往新西兰等地的午夜。然后在午夜之后回到亚洲。然后是印度等几个小时后到达欧洲的午夜,然后是北美东海岸,晚些时候再过几个小时。所有这些地方都经历过不同时刻的 same LocalDateTime ,每次交易都由不同的 ZonedDateTime 对象。

所以...



关于第二个项目符号,请注意几乎所有数据库系统将使用区域信息将日期时间调整为UTC并存储该UTC值。有些还保存区域信息,但某些(如Postgres)在使用它调整为UTC后丢弃区域信息。所以带时区是一个用词不当的地方,真的意味着尊重时区。如果您关心记住原始区域,您可能需要将其名称保存在一个单独的列中。

提示:对DST和时区的频繁更改意味着您必须保持时区 tzdata 数据库是最新的。在你的主机操作系统,你的JVM中,或者在你的数据库系统中,例如Postgres,都有一个tzdata。所有这三个应该经常更新。有时,这些区域的变化速度比计划的更新周期更快,例如土耳其去年决定在数周前通知DST。所以你可能偶尔需要手动更新这些tzdata文件。 Oracle提供了一个更新其Java实现的tzdata的工具。

处理精确时刻的一般最佳做法是用UTC跟踪它们。仅在必要时才应用时区,例如向用户展示他们希望在自己的教区时区中看到值的用户。在java.time中, Instant 类表示时间轴中的某一时刻。 UTC的分辨率为纳秒。

 即时即时= Instant.now(); // UTC中时间轴上的当前时刻。 
ZonedDateTime zdt = instant.atZone(z); //分配一个时区,通过特定区域的挂钟时间的镜头查看同一时刻。
即时即时= zdt.toInstant(); //恢复到UTC,剥离时区。但时间线上仍然是同一时刻。

顺便说一句,符合JDBC 4.2及更高版本的驱动程序可以直接处理java.time类型通过:


  • PreparedStatement :: setObject

  • ResultSet :: getObject



避免旧的遗留数据类型只要可能, java.util.Date java.sql.Timestamp 它们设计不佳,混乱和缺陷。



了解所有这四个都是UTC时间轴上某一刻的表示:


  • Modern


    • java.time.Instant

    • java.time.OffsetDateTime ,指定的偏移量为 ZoneOffset.UTC


  • 传统


    • java.util.Date

    • java.sql.Timestamp



    • $ b

      如果您想要一个没有时间和没有时区的仅限日期的值,请使用 code> java.time.LocalDate 。这个类代替 java.sql.Date



      至于特定的数据库,请注意SQL标准几乎没有触及关于日期 - 时间类型及其处理的主题。此外,各种数据库的差异很大,我的意思是广泛,支持日期时间功能。有些几乎没有支持。有些将SQL标准类型与专有类型混合使用,这些类型要么早于标准类型,要么作为标准类型的替代品。另外,JDBC驱动程序的行为与将日期时间值封送到数据库或从数据库封装日期时间值不同。一定要研究文件和练习,练习,练习。

      This might be a stupid question with an implicit/straight forward answer, but somehow I am not able to wrap my head around it.

      My requirement is to store all dates & date-times in UTC timezone in the database. I am using Java 8's LocalDate & LocalDateTime in my Hibernate entities.

      Is that correct as LocalDate & LocalDateTime doesn't have timezone associated with them?

      If not, should I fall back to using good old (or legacy?) Date & Timestamp?

      Or should I be using Java 8's Instant? If using Instant, will there be a possibility to store only the date part, without time?

      If it makes any difference, the database on which I want them to work is MySQL & SQL Server.

      Again, if it makes further difference, then it is a Spring Boot application.

      Thanks!!

      解决方案

      The "Local…" types purposely have no concept of time zone. So they do not represent a moment on the timeline. A LocalDateTime represents a vague range of possible moments but has no real meaning until assigning an offset or time zone. That means applying a ZoneId to get a ZonedDateTime.

      For example, to say that Christmas this year starts at the first moment of December 25, we say:

      LocalDateTime ldt = LocalDateTime.of( 2017 , 12 , 25 , 0 , 0 , 0 , 0 );
      

      But that stroke of midnight happens earlier in the east than in the west.

      That is why the elves’ Logistics department maps out Santa’s route starting at Kiribati in the Pacific, the earliest time zone in the world at 14 hours ahead of UTC. After delivering there, they route Santa westward to places like New Zealand for its midnight later. Then on to Asia for their midnight later. Then India, and so on, reaching Europe for their midnight several hours later, and then the east coast of North America for their midnight a few hours more later. All of these places experienced that same LocalDateTime at different moments, each delivery represented by a different ZonedDateTime object.

      So…

      • If you want to record the concept of Christmas starting after midnight on the 25th, use a LocalDateTime and write into a database column of type TIMESTAMP WITHOUT TIME ZONE.
      • If you want to record the exact moment of each delivery Santa makes, use a ZonedDateTime and write into a database column of type TIMESTAMP WITH TIME ZONE.

      About that second bullet, be aware that nearly every database system will use the zone information to adjust the date-time to UTC and store that UTC value. Some save the zone information as well, but some such as Postgres discard the zone info after using it to adjust into UTC. So "with time zone" is something of a misnomer, really meaning "with respect for time zone". If you care about remembering that original zone, you may need to store its name in a separate column alongside.

      Another reason to use Local… types is for future appointments. Politicians enjoy frequently changing their time zone(s) of their jurisdiction. They like to adopt Daylight Saving Time (DST). The like to change the dates of their DST cutovers. They like to drop their adoption of DST. They like to redefine their time zones, changing the boundaries. They like to redefine their offset-from-UTC sometimes by amounts like 15 minutes. And they rarely give advance notice, making such changes with as little as a month or two of warning.

      So to make medical check-up appointment for next year or in six months, the time zone definition cannot be predicted. So if you want an appointment of 9 AM, you should use a LocalTime or LocalDateTime recorded in a database column of type TIMESTAMP WITHOUT TIME ZONE. Otherwise that 9 AM appointment, if zoned where the DST cutover is postponed, may appear as 8 AM or 10 AM.

      When generating a projected schedule, you can apply a time zone (ZoneId) to those "local" (unzoned) values to create ZonedDateTime objects. But do not rely on those too far out in time when politicians may ruin their meaning by changing the zone(s).

      Tip: These frequent changes to DST and time zones means you must keep your time zone tzdata data base up to date. There is a tzdata in your host OS, your JVM, and perhaps in your database system such as Postgres. All three should be frequently updated. Sometimes the zones change faster than the planned update cycles of those products such as Turkey last year deciding to stay on DST with only several weeks notice. So you may occasionally need to manually update those tzdata files. Oracle provides a tool for updating the tzdata of their Java implementations.

      The general best practice in handling exact moments is to track them in UTC. Apply a time zone only where necessary such as in presentation to a user where they expect to see values in their own parochial time zone. In java.time, the Instant class represents a moment in the timeline. In UTC with a resolution of nanoseconds.

      Instant instant = Instant.now() ;  // Current moment on the timeline in UTC.
      ZonedDateTime zdt = instant.atZone( z ) ;  // Assign a time zone to view the same moment through the lens of a particular region’s wall-clock time.
      Instant instant = zdt.toInstant();  // revert back to UTC, stripping away the time zone. But still the same moment in the timeline.
      

      By the way, drivers that comply with JDBC 4.2 and later can deal directly with the java.time types via:

      • PreparedStatement::setObject
      • ResultSet::getObject

      Avoid the old legacy data types such as java.util.Date and java.sql.Timestamp whenever possible. They are poorly designed, confusing, and flawed.

      Understand that all of these four are representations of a moment on the timeline in UTC:

      • Modern
        • java.time.Instant
        • java.time.OffsetDateTime with an assigned offset of ZoneOffset.UTC
      • Legacy
        • java.util.Date
        • java.sql.Timestamp

      If you want a date-only value without time-of-day and without time zone, use java.time.LocalDate. This class supplants java.sql.Date.

      As for specific databases, be aware that the SQL standard barely touches on the topic of date-time types and their handling. Furthermore, the various databases vary widely, and I really mean widely, in their support of date-time features. Some have virtually no support. Some mix SQL standard types with proprietary types that either predate the standard types or are intended as alternatives to the standard types. In addition, JDBC drivers differ in their behavior with marshaling date-time values to/from the database. Be sure to study the documentation and practice, practice, practice.

      这篇关于Hibernate与Java 8 LocalDate&数据库中的LocalDateTime的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

使用 Local ... 类型的另一个原因是为将来的约会。政治家喜欢经常改变他们辖区的时区。他们喜欢采用夏令时(DST)。喜欢改变他们DST切换的日期。他们喜欢放弃采用DST。他们喜欢重新定义他们的时区,改变边界。他们喜欢重新定义它们的UTC偏移量,有时候会像15分钟那样。他们很少提前发出通知,在短短一个月或两个小时内发出警告。

因此,为明年或六个月进行体检,无法预测时区定义。因此,如果您想约定上午9点,则应该使用记录在类型数据库列中的 LocalTime LocalDateTime 没有时区的TIMESTAMP 。否则,上午9点的约会,如果在夏令时延期交割区划分,可能会显示为上午8点或上午10点。



在生成预计时间表时,您可以将时间区域( ZoneId )添加到这些本地(未分区)值以创建 ZonedDateTime 对象。但是,当政客们通过改变区域可能毁掉他们的意义时,不要依赖那些时间太远的人。

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆