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 setsTimeZone.setDefault(TimeZone.getTimeZone("UTC"));
- Caching is disabled in persistence.xml
Here's what happens:
- Entity A has a field
syncTimestamp
ofjava.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
精彩评论