开发者

JPA, Glassfish, Mysql: UTC time conversion occuring twice

开发者 https://www.devze.com 2023-04-01 19:56 出处:网络
I\'m going nuts here... I have recently noticed that time is mis-presented in my JPA-managed entities, when I access a Date field:

I'm going nuts here... I have recently noticed that time is mis-presented in my JPA-managed entities, when I access a Date field:

  • My personal timezone is CEST, same for the machine that runs Glassfish and MySQL.
  • Glassfish is instructed to use UTC as default Timezone: a @Startup-bean sets TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
  • Caching is disabled in persistence.xml

Here's what happens:

  • Entity A has a field syncTimestamp of java.util.Date.
  • When a particular REST resource is triggered, the timestamp is set to now: a.setSyncTimestamp(new Date()). Let's assume my clock on the wall says 14:30:00h (date omitted for brevity).
  • The entity is managed, so the update ends up in the DB. The row in the database (of type DATETIME) shows the expected value "12:30:00h" - CEST is currently 2h ahead of UTC.
  • Accessing the getter in the same transaction outputs the timestamp as "12:30:00.123Z" (note the milliseconds).
  • Accessing the getter in a separate transaction, after retrieving the entity from the database again (disabled caching), outputs "10:30:00Z".

So when loading the entity from the DB, it looks like JPA converted again from what it thinks was a CEST timestamp to UTC, substracting 2 hours.

I've read plenty posts about JPA and timezone, etc. What I learned was: neither java.util.Date nor MySQL 开发者_运维技巧DATETIME have an understanding of Timezones. This should not be a problem, as long as everything is always considered "UTC", right? Now why does JPA (I think?) convert the value?

(PS: I found a related post. It suggests to put the JVM into Timezone UTC -- but isn't this what my Startup Bean does?)

EDIT: Turns out a crucial bit of information was missing. In order to prepare for Glassfish clustering, I had moved the database for the EJB Timer Service to my MySQL DB. As a result, the JDBC driver was extracted from the application to the glassfish lib-directory.


Ok, I have found out what was happening, and how to fix it.

It looks like that because of the EJB Timer Service is being started before my @Startup-bean, the mysql JDBC driver is being loaded and initialized with the timezone (which at that time is system default = CEST).

Setting the default Timezone to UTC later does not affect the JDBC driver anymore (is that maybe a glassfish bug?).

Solution is to set the default timezone of the JVM to UTC:

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

精彩评论

暂无评论...
验证码 换一张
取 消