Java夏令时和Hibernate

时间:2013-01-07 20:10:14

标签: java hibernate h2 dts

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

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

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

更新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

但在数据库中有以下内容:

in the database

3 个答案:

答案 0 :(得分: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作为本地时间运行应用程序。如果在任何地方需要用户的本地时间,例如在用户界面中,这就有缺点。

  4. 我们在我们的申请中做了解决方案1.

答案 1 :(得分:0)

如Johanna所述,如何处理这个时区转换问题有几种选择。还有一篇文章以更详细的方式解释了这个问题,提供了更多的例子和解决方案。

考虑到上一个答案中的选项编号1,并且您不想自己编写所有代码,您可以使用一个小型开源库DbAssist 。它将java.util.Datejava.util.Timestamp映射到自定义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 Annotations或HBM文件映射您的实体字段而有所不同;这是一个简单的单线设置。

答案 2 :(得分:0)

你能解释一下你桌子的数据结构吗?您是否在该列中使用DATETIME或TIMESTAMP?

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

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