使用 JPA 的 WildFly 时区

WildFly Timezone with JPA

我目前使用 Hibernate 和 WildFly 开发一个项目。我使用的数据库是 mariaDB。

当我将 java.time.Instant 插入数据库时​​,JPA 对插入的时间戳应用两个小时(在 java 代码中始终为 UTC)。

我尝试在 standalone.conf(Java 选项)和命令行参数中使用 -Duser.timezone=UTC 启动 WildFly。管理控制台显示这个时区,但所有日志输出和数据库输入都在我的系统时区 (+2)。当我将 Windows 时区设置为 UTC 时,奇怪的行为停止并且数据库中的时间是正确的。

我还尝试设置休眠 属性 <property name="hibernate.jdbc.time_zone" value="UTC"/> 和我的 mariaDB SET GLOBAL time_zone = "+00:00" 但效果不佳。

我在这里错过了什么?

如果您想确保您的 Java 应用程序始终为 UTC,您应该在应用程序启动时覆盖 JVM 时区。

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

来源

How do I programmatically set the time zone in Java?

通过这样做,您将覆盖部署服务器的任何其他奇怪的时区配置,我的理解是您在这里期望的行为。

此代码应添加到应用程序启动中。这取决于您使用的框架。

对于 JEE5+,您可以创建单例 boostrap EJB:

@Singleton
@Startup
public class StartupBean {

    @PostConstruct
    private void startup() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
}

对于 Springboot 1.5+,你可以在任何地方创建一个钩子:

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}

所以这个问题的答案很简单。

我使用了 WildFly12 打包的 Hibernate 版本——5.1.10。根据Chris Cranford

the hibernate.jdbc.time_zone setting wasn't introduced until 5.2.3

虽然这里没有任何子系统抛出错误。更新您的 Hibernate 即可解决问题。

  1. 进入wildfly-12.0.0.Final\modules\system\layers\base\org\hibernate\main
  2. 下载core and envers库并将其放入文件夹。
  3. 修改 module.xml 并更新版本并删除 -java8-* 和 entitymanger-*.jar -> 它们已弃用并移入核心。
  4. 重新启动您的 WildFly,您的问题就会消失。

WildFly 团队没有使用较新的 Hibernate 版本可能有充分的理由,但我不确定原因。所以这可能是您在交换库时遇到了一些错误/不需要的行为。

实际上,属性 未知的简单错误消息可以节省我一些时间。要么我没有在日志中找到它,要么这不是错误...