Hibernate日期转换

时间:2010-09-07 00:29:09

标签: java hibernate date timezone jodatime

在实体中设置日期字段时,我遇到了与hibernate相关的奇怪问题。 日期在java程序中被解释为UTC(我做了一个System.out以确保分配的日期是'UTC'。但是,当hibernate实际上持续存储到数据库时,日期将转换为本地时间并存储) 恩。该值已在实体设置器中设置为“2009-09-09 00:08:08” - GMT 持续到数据库的实际值是“2009-09-08 08:08:08” - 美国东部时间。 我无法找出发生的地点和原因以及如何防止它。感谢

P.S。我正在使用joda日期库并注释该字段 @ org.hibernate.annotations.Type(type =“org.joda.time.contrib.hibernate.PersistentDateTime”)

3 个答案:

答案 0 :(得分:3)

  

但是,当hibernate实际上持久存储到数据库时,日期将转换为本地时间并存储)ex。该值已在实体设置器中设置为“2009-09-09 00:08:08” - GMT持续到数据库的实际值为“2009-09-08 08:08:08” - 美国东部时间。< / p>

好的,首先,无论您使用哪种列类型在MySQL中存储日期(TIMESTAMP或DATETIME),都不存储时区。来自Re: Storing timezone with datetime

  
      
  • TIMESTAMP是自1970年以来的秒数,占4个字节。它存储在GMT中。也就是说,TZ偏移量在您存储值时应用,然后在您获取时重新应用。 (...)

  •   
  • DATETIME是一个8字节的数字字符串“yyyymmddhhmmss”。 (...)

  •   

第二,除非buggy behavior,我的理解是转换应该由服务器或JDBC驱动程序完成,具体取决于the server time zone设置,这样就不会出现不一致数据

在这两种情况下,我的观点是存储“2009-09-09 00:08:08” - GMT “2009-09-08 08:08:08” - 美国东部时间 来自Java 应该在数据库中产生相同的值

但是,当显示时,看起来会进行不同的转换。这引出了一个问题:你是如何实际检查“持久日期”的值的。 SQL客户端中是否出现“问题”?在Java代码中?

参考


  

DateTime的MySQL文档说“MySQL以'YYYY-MM-DD HH:MM:SS'格式检索并显示DATETIME值”。这意味着mysql将“自纪元以来的毫秒”转换为上述格式。所以现在我的问题是,时区信息也存储在mysql中吗?

我已经更新了我的初步答案(这不完全准确/详尽)。无论您使用的是DATETIME还是TIMESTAMP,答案都是否定的。

  

我做的另一个观察是,只有当我在Java应用程序中设置日期时,上述日期“转换”问题才存在。如果我使用'UTC_TIMESTAMP()'创建一个mysql触发器来更新/设置日期,则日期将显示在'UTC'时间内。

UTC_TIMESTAMP()函数始终会返回当前的 UTC 日期和时间。


我想知道的是:

  • 你是如何“揭露”这个问题的?使用SQL客户端还是来自Java?
  • JVM的本地时区是什么?
  • 什么是MySQL服务器时区?
  • MySQL JDBC驱动程序的版本是什么?
  • 您可以使用原始JDBC进行测试吗?

答案 1 :(得分:1)

为了在数据库中将日期视为UTC(用于读/写),您可以使用这个小型开源库DbAssist。它使用自定义UtcDateType来映射实体中的java.util.Date字段,以便它们在数据库中被Hibernate视为UTC。由于您使用的是JPA注释,因此您将使用以下依赖项:

<dependency>
    <groupId>com.montrosesoftware</groupId>
    <artifactId>DbAssist-5.2.2</artifactId>
    <version>1.0-RELEASE</version>
</dependency>

应用此修复很容易,例如,使用Spring Boot时,您必须确保在应用程序类之前有@EnableAutoConfiguration注释。如果您使用的是其他Hibernate版本,请参阅github wiki以找到正确版本的修补程序和安装指南。您还可以在此article中详细了解时区转换问题。

答案 2 :(得分:0)

Joda Time Contrib的这种行为在我的项目Usertype for Joda Time和JSR310中得到修复。请参阅http://usertype.sourceforge.net/,这实际上是JodaTime Hibernate的替代品。

我已经写过关于这个问题:http://blog.jadira.co.uk/blog/2010/5/1/javasqldate-types-and-the-offsetting-problem.html

希望这有帮助,

克里斯