使用 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 即可解决问题。
- 进入wildfly-12.0.0.Final\modules\system\layers\base\org\hibernate\main
- 下载core and envers库并将其放入文件夹。
- 修改 module.xml 并更新版本并删除 -java8-* 和 entitymanger-*.jar -> 它们已弃用并移入核心。
- 重新启动您的 WildFly,您的问题就会消失。
WildFly 团队没有使用较新的 Hibernate 版本可能有充分的理由,但我不确定原因。所以这可能是您在交换库时遇到了一些错误/不需要的行为。
实际上,属性 未知的简单错误消息可以节省我一些时间。要么我没有在日志中找到它,要么这不是错误...
我目前使用 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 即可解决问题。
- 进入wildfly-12.0.0.Final\modules\system\layers\base\org\hibernate\main
- 下载core and envers库并将其放入文件夹。
- 修改 module.xml 并更新版本并删除 -java8-* 和 entitymanger-*.jar -> 它们已弃用并移入核心。
- 重新启动您的 WildFly,您的问题就会消失。
WildFly 团队没有使用较新的 Hibernate 版本可能有充分的理由,但我不确定原因。所以这可能是您在交换库时遇到了一些错误/不需要的行为。
实际上,属性 未知的简单错误消息可以节省我一些时间。要么我没有在日志中找到它,要么这不是错误...