2013-01-07 80 views
3

我找到了一种方法来创建我想用UTC时区哪个日期: Java Date and Daylight SavingJava的夏令时和Hibernate

这样我就可以打造“阳光03月25日02:00:00”,但是当我插入此日期Hibernate,它不写它,似乎休眠使用不能覆盖的不同时区。

我的问题是,我不能在我的Hibernate/H2数据库中插入这个日期:“Sun 3月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

+0

从这个问题和你的另一个*你想要哪个* 2am还不清楚。凌晨2点UTC?或在当地时区凌晨2点?你说你*不能*插入价值 - 当你尝试时会发生什么?更新了 –

+0

。这不是重要的时区,我会插入“2012年3月25日02:00:00”,但它不起作用。 – tyranitar

+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。

+0

我选择了2号解决方案 – tyranitar

0

正如约翰娜所说,有几个选择如何处理这个时区转移问题。还有一篇文章更详细地解释了这个问题,提供了更多的例子和解决方案。

就上一个答案中的选项编号1而言,如果您不想自己编写所有代码,则可以使用小型开源库DbAssist 。它将java.util.Datejava.util.Timestamp映射到自定义UtcDateType,该自定义内部覆盖了setter和getter,因此无论何时读取或写入数据库,它都会将数据库中的日期视为UTC时区。这是一个方便的解决方案,因为你根本没有改变你的实体类。

所有你所要做的就是增加的依赖(与你的Hibernate的版本替换5.2.2):

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

然后应用修复作为该项目的github安装手册的说明。我不在这里复制它,因为它取决于您是使用JPA Annotations还是HBM文件映射您的实体字段而有所不同;这是一个简单的单线设置。

0

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

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

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