3

我找到了一种使用 UTC 时区创建我想要的日期的方法: Java Date and Daylight Saving

所以我可以创建“Sun Mar 25 02:00:00”,但是当我在 Hibernate 中插入这个日期时,它没有写它,似乎休眠使用了我无法覆盖的不同时区。

我的问题是,如果我使用 UTC 时区,我无法在这个日期插入我的 Hibernate/H2 数据库:“Sun Mar 25 02:00:00”。

更新1:我正在尝试插入这些值:

Sun Mar 25 01:00:00 UTC 2012
Sun Mar 25 02:00:00 UTC 2012
Sun Mar 25 03:00:00 UTC 2012
Sun Mar 25 04:00:00 UTC 2012
Sun Mar 25 05:00:00 UTC 2012
Sun Mar 25 06:00:00 UTC 2012
Sun Mar 25 07:00:00 UTC 2012
Sun Mar 25 08:00:00 UTC 2012
Sun Mar 25 09:00:00 UTC 2012
Sun Mar 25 10:00:00 UTC 2012
Sun Mar 25 11:00:00 UTC 2012
Sun Mar 25 12:00:00 UTC 2012
Sun Mar 25 13:00:00 UTC 2012
Sun Mar 25 14:00:00 UTC 2012
Sun Mar 25 15:00:00 UTC 2012
Sun Mar 25 16:00:00 UTC 2012
Sun Mar 25 17:00:00 UTC 2012
Sun Mar 25 18:00:00 UTC 2012
Sun Mar 25 19:00:00 UTC 2012
Sun Mar 25 20:00:00 UTC 2012
Sun Mar 25 21:00:00 UTC 2012
Sun Mar 25 22:00:00 UTC 2012
Sun Mar 25 23:00:00 UTC 2012

但在数据库中有这些:

在数据库中

4

3 回答 3

1

这是 JDBC 的“特性”,而不是 Hibernate。因此,您可以在 jdbc 选项(hibernate.cfg.xml 中的 jdbc 连接字符串)中而不是在 Hibernate 选项中更改此行为。默认情况下,日期值始终保存在客户端应用程序的时区中(而不是数据库的时区,因为它似乎更符合逻辑)。例如,MySQL 知道一个 jdbc 连接选项,它强制数据库始终以 UTC 存储日期值。我不知道 H2 是否知道这样的选择,可能不是。

在您的示例中,3 月 25 日是您的白天时间的第一天。3 月 25 日 02:00 在您的时区中不存在,这就是您在数据库中找不到它的原因。

如果您不想要连接字符串中的选项(它的缺点可能并非在所有数据库上都可用),那么有三种可能性可以解决这个问题:

  1. 在插入之前和阅读之后,您会在程序中进行时区对话。为此,除了您的普通 getter get/setMyTime() 之外,您还为 Hibernate get/setHibernateMyTime() 编写了一个额外的 getter 和 setter,您可以在其中进行时区转换,并在映射文件或注释中使用它们。对于时区转换,您可以使用 TimeZone.getOffset()。

  2. 使用字符串而不是日期。在这种情况下,您不需要进行时区转换,但您必须将字符串转换为日期,反之亦然。

  3. 以 UTC 作为本地时间运行应用程序。如果在任何地方都需要用户的本地时间,例如在用户界面中,这将具有缺点。

我们在我们的应用程序中做了解决方案 1.。

于 2013-01-08T07:45:59.687 回答
0

你能解释一下你的表的数据结构吗?您在为该列使用 DATETIME 或 TIMESTAMP 吗?

根据 MySQL 官方文档 - MySQL 将 TIMESTAMP 值从当前时区转换为 UTC 进行存储,然后从 UTC 转换回当前时区进行检索。它使用 JDBC 连接的当前时区进行此转换。

这种行为很奇怪但正确,“Sun Mar 25 02:00:00”在您的时区(可能是欧洲中部)中不存在。如果您需要保存该日期,您可以将列创建为 DATETIME。

于 2016-11-24T20:14:54.293 回答
0

正如 Johanna 所提到的,有几种方法可以处理这个时区偏移问题。还有一篇文章更详细地解释了这个问题,提供了更多的例子和解决方案。

考虑到上一个答案中的选项 1 并且您不想自己编写所有代码,您可以使用小型开源库DbAssist java.util.Date它将and映射java.util.Timestamp到一个 custom UtcDateType,它在内部覆盖 setter 和 getter,以便在读取或写入数据库时​​将数据库中的日期视为 UTC 时区。这是一个方便的解决方案,因为您根本不需要更改实体类。

您所要做的就是添加依赖项(将 5.2.2 替换为您的 Hibernate 版本):

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

然后按照项目github上的安装指南中的说明应用修复程序。我不会在这里复制它,因为它会根据您是使用 JPA 注释还是 HBM 文件来映射您的实体字段而有所不同;不过,这是一个简单的单线设置。

于 2016-11-15T15:09:07.543 回答