7

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

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

4

3 回答 3

3

但是,当休眠实际持久化到数据库时,日期会转换为本地时间并存储)例如。该值已在实体设置器中设置为“2009-09-09 00:08:08” - GMT 保存到数据库的实际值是“2009-09-08 08:08:08” - 美国东部时间。

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

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

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

其次,除非出现错误行为,否则我的理解是转换应该由服务器或 JDBC 驱动程序完成,具体取决于服务器时区设置,这样您就不会得到不一致的数据。

在这两种情况下,我的观点是存储“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 做一个测试吗?
于 2010-09-07T01:12:12.300 回答
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以找到正确的修复版本和安装指南。您还可以在本文中阅读有关时区偏移问题的更多信息。

于 2016-11-08T13:09:27.230 回答
0

Joda Time Contrib 的这种行为已在我的 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

希望这可以帮助,

克里斯

于 2011-04-16T20:58:41.030 回答