JPA,Glassfish,Mysql:UTC时间转换发生两次

时间:2011-09-02 13:23:54

标签: mysql datetime java-ee jpa

我在这里疯了......我最近注意到,当我访问Date字段时,我的JPA管理实体中的时间错误呈现:

  • 我的个人时区是CEST,与运行Glassfish和MySQL的机器相同。
  • Glassfish被指示使用UTC作为默认时区:@Startup - bean设置TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
  • 在persistence.xml中禁用缓存

以下是发生的事情:

  • 实体A的字段syncTimestampjava.util.Date
  • 触发特定REST资源时,时间戳设置为now:a.setSyncTimestamp(new Date())。让我们假设墙上的时钟是14:30:00h(为简洁起见省略了日期)。
  • 管理实体,因此更新最终会在数据库中完成。数据库中的行(DATETIME类型)显示预期值“12:30:00h” - CEST目前比UTC早2h。
  • 在同一事务中访问getter会将时间戳输出为“12:30:00.123Z”(请注意毫秒数)。
  • 在再次从数据库中检索实体(禁用缓存)后,在单独的事务中访问getter,输出“10:30:00Z”。

因此,当从数据库加载实体时,看起来JPA再次从它认为是CEST时间戳的转换为UTC,减去2小时。

我已经阅读了很多关于JPA和时区等的帖子。我学到的是:java.util.Date和MySQL DATETIME都不了解时区。这应该不是问题,只要一切都被视为“UTC”,对吗?现在为什么做JPA(我认为?)转换值?

(PS:我发现了related帖子。它建议将JVM放入时区UTC - 但这不是我的Startup Bean所做的吗?)

编辑:原来缺少一些关键信息。为了准备Glassfish集群,我已将EJB Timer Service的数据库移动到我的MySQL DB。因此,JDBC驱动程序从应用程序提取到glassfish lib目录。

1 个答案:

答案 0 :(得分:3)

好的,我已经知道发生了什么,以及如何解决它。

看起来因为EJB Timer Service正在之前我的@Startup - bean启动,所以mysql JDBC驱动程序正在加载并使用时区进行初始化(当时是系统默认= CEST)。

以后将默认时区设置为UTC不会再影响JDBC驱动程序(这可能是一个玻璃鱼错误吗?)。

解决方案是将JVM的默认时区设置为UTC:

asadmin create-jvm-options -Duser.timezone=UTC
asadmin restart-domain