mysql - JPA、Glassfish、Mysql : UTC time conversion occuring twice

标签 mysql datetime jakarta-ee jpa

我快要疯了...我最近注意到,当我访问 Date 字段时,JPA 管理的实体中的时间显示错误:

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

发生的情况是这样的:

  • 实体 A 的字段 syncTimestampjava.util.Date
  • 触发特定 REST 资源时,时间戳设置为现在:a.setSyncTimestamp(new Date())。假设墙上的时钟显示为 14:30:00(为简洁起见,省略了日期)。
  • 该实体是受管理的,因此更新最终会在数据库中进行。数据库中的行(DATETIME 类型)显示预期值“12:30:00h” - CEST 目前比 UTC 早 2 小时。
  • 在同一事务中访问 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 计时器服务的数据库移至 MySQL 数据库。结果,JDBC 驱动程序从应用程序中提取到 glassfish lib 目录中。

最佳答案

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

看起来由于 EJB 计时器服务在我的 @Startup-bean 之前启动,因此正在加载 mysql JDBC 驱动程序并使用时区进行初始化(当时系统默认 = CEST)。

稍后将默认时区设置为 UTC 不会再影响 JDBC 驱动程序(这可能是 glassfish 错误吗?)。

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

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

关于mysql - JPA、Glassfish、Mysql : UTC time conversion occuring twice,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7284067/

相关文章:

mysql - 使用 MySQL/InnoDB 重新平衡表分片

mysql - 如何在加载到 MySQL 时自动转换时区

java - 将任意数据与 ejb 调用上下文关联

java - 带有重音符号的编码错误。峰会形成时的 Spring-Mvc

php - sql group by 重复结果

php - 如何在 Laravel 中对所有行使用多态关系?

具有 50+ 百万行的 MySQL 表 - 如何使用索引加快搜索速度?

datetime - 如何在 PowerShell 中将 DateTime 作为参数传递?

javascript - 如何在javascript中将天数添加到现在的日期?

java - 如何设置 Context.INITIAL_CONTEXT_FACTORY?没有初始上下文异常?