繁体   English   中英

在 Spring 引导中使用 JVM -Duser.timezone 动态设置 MySql 时区

[英]Set MySql time zone dynamically with JVM -Duser.timezone in Spring Boot

我在“IST”TZ 中有一个 Ubuntu 16 服务器。
“IST”TZ 中的 MySQL (v5.7) 服务器。
Spring-boot (v2), Java (v1.8) jar 在“美国/洛杉矶”TZ。 从 -Duser.timezone arg 设置。

Problem: As my Java Date obj is in "America/Los_Angeles" TZ, fetching MySQL data was not working as MySQL date was a day behind from java date.
Found the above difference in Java when logged actual date obj (query parameter obj to be used) without passing it to query and the java object fetched from MySQL after select *.

解决方案:在 application.properties 中添加“spring.jpa.properties.hibernate.jdbc.time_zone = America/Los_Angeles”。 它按预期工作得很好。

问题:
1. 有什么方法可以将 MySQL TZ 与 spring 引导 Java 应用程序 TZ 对齐,通过“-Duser.timezone 参数”传递?
2.在MySQL DB中,我可以查看每个连接的时区吗? 与中类似,我可以从“show processlist”查询中看到连接列表。

tl;博士

使用java.time类来避免您的时区问题。

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
myPreparedStatament.setObject( … , java.time.OffsetDateTime.now( z ) ) ;   // Persisting
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;   // Retrieval
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;                           // Adjust into the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline.

java.time

我的 Java 日期 obj

The Date classes ( java.util.Date & java.sql.Date ) are both terrible, now legacy, supplanted years ago by the modern java.time classes defined in JSR 310.

我在“IST”TZ 中有一个 Ubuntu 16 服务器。

仅供参考,服务器通常最好设置为默认时区 UTC (GMT),偏移量为零时分秒。 请注意,主机操作系统有自己的默认时区,JVM 有自己的默认时区。 与您的数据库交互的 session 等中间件可能有自己的当前默认时区。

作为 Java 程序员,您永远不应该依赖当前的默认时区。 JVM 内任何应用程序的任何线程中的任何代码都可以在运行时随时更改默认值。 因此,最好指定预期/期望的时区。

“spring.jpa.properties.hibernate.jdbc.time_zone = America/Los_Angeles”

如果您与数据库交换java.time类而不是使用字符串或旧的日期时间类,则不需要此设置。 JDBC 4.2, later versions of Hibernate, and JPA 2.2 all require support for java.time objects.

有什么方法可以将 MySQL TZ 与 spring 启动 Java 应用程序 TZ 对齐,通过“-Duser.timezone”参数动态传递?

如果您将java.time对象与数据库交换,这个问题就会变得没有意义,问题就会消失,您的生活会变得更轻松。

在 MySQL DB 中,我可以检查每个连接的时区吗? 与中类似,我可以从“show processlist”查询中看到连接列表。

同上,使用java.time对象,问题变得没有意义。

示例代码

仅日期,无时间,无时区

对于类似于 SQL 标准DATE的列类型,请使用java.time.LocalDate

ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
myPreparedStatament.setObject( … , LocalDate.now( z ) ) ;      // Persisting
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;  // Retrieval

时刻,时间轴上的一个点

对于类似于 SQL 标准TIMESTAMP WITH TIME ZONE的列类型,请使用java.time.OffsetDateTime (可选InstantZonedDateTime )。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
myPreparedStatament.setObject( … , java.time.OffsetDateTime.now( z ) ) ;      // Persisting
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;  // Retrieval

不是片刻,只是日期和时间

对于类似于 SQL 标准TIMESTAMP WITHOUT TIME ZONE的列类型,请使用java.time.LocalDateTime 请注意:缺少任何时区或与 UTC 偏移的概念意味着此数据类型不能代表时刻,也不是时间线上的一个点。

myPreparedStatament.setObject( … , LocalDateTime.of( 2020 , Month.MAY , 15 , 22 , 0 , 0 , 0 ) ;  // Persisting
LocalDateTime let = myResultSet.getObject( … , LocalDateTime.class ) ;                           // Retrieval

Java(传统和现代)和标准 SQL 中的日期时间类型表


关于java.time

java.time框架内置于 Java 8 及更高版本中。 这些类取代了麻烦的日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle 教程 并在 Stack Overflow 上搜索许多示例和解释。 规范是JSR 310

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC 驱动程序 不需要字符串,不需要java.sql.*类。

从哪里获得 java.time 课程?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM