Java夏令时和Hibernate

Java夏令时和Hibernate,java,hibernate,h2,dts,Java,Hibernate,H2,Dts,我找到了使用UTC时区创建所需日期的方法: 所以我可以创建“Sun Mar 25 02:00:00”,但当我在Hibernate中插入这个日期时,它不会写入它,似乎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

我找到了使用UTC时区创建所需日期的方法:

所以我可以创建“Sun Mar 25 02:00:00”,但当我在Hibernate中插入这个日期时,它不会写入它,似乎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
但在数据库中有以下内容:

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

在你的例子中,3月25日是白天的第一天。3月25日02:00在您的时区中不存在,这就是为什么您在数据库中找不到它

如果您不想在连接字符串中使用选项(其缺点是可能无法在所有数据库中使用),则有三种可能的解决方法:

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

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

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


  • 我们完成了解决方案1。在我们的应用程序中。

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

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

    您只需添加依赖项(用Hibernate版本替换5.2.2):

    
    com.montrose软件
    
    . 我不是在这里复制它,因为它根据您是使用JPA注释还是HBM文件来映射实体字段而有所不同;这是一个简单的单行设置。

    您能解释一下表的数据结构吗?您是在为该列使用DATETIME还是时间戳

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


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

    从这个问题和您的另一个问题来看,仍然不清楚您想要哪一个凌晨2点。协调世界时凌晨2点?或者在当地时区凌晨2点?您说您无法插入值-尝试时会发生什么?已更新。时区并不重要,我会插入“Sun Mar 25 02:00:00 2012”,但它不起作用。时区绝对重要。您的数据库本身是否有任何时区设置?也许这就是问题所在。我使用的是Hibernate和H2,我没有找到任何选项来设置数据库时区如何插入数据,如何查询数据?根据使用的方法,小时数将进行调整,因为时间不存在。如果使用
    java.util.Date
    /
    java.sql.Timestamp
    ,就会发生这种情况。如果以字符串形式插入并读取数据,则不会对H2的最新版本进行调整,因为在内部,H2不再使用
    java.util.Calendar
    /
    java.util.Date
    /
    java.sql.Date/Time/Timestamp
    (正是出于这个原因)。