簡體   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