Domanda

I found a way to create which date I want using the UTC timezone: Java Date and Daylight Saving

So I can create "Sun Mar 25 02:00:00" but when I insert this date in Hibernate, it doesn't write it, seems that hibernate uses a different timezone that I can't overwrite.

My problem is that I can't insert in my Hibernate/H2 database this date: "Sun Mar 25 02:00:00" neither if I use the UTC timezone.

UPDATE 1: I'm trying to insert these values:

Sun Mar 25 01:00:00 UTC 2012
Sun Mar 25 02:00:00 UTC 2012
Sun Mar 25 03:00:00 UTC 2012
Sun Mar 25 04:00:00 UTC 2012
Sun Mar 25 05:00:00 UTC 2012
Sun Mar 25 06:00:00 UTC 2012
Sun Mar 25 07:00:00 UTC 2012
Sun Mar 25 08:00:00 UTC 2012
Sun Mar 25 09:00:00 UTC 2012
Sun Mar 25 10:00:00 UTC 2012
Sun Mar 25 11:00:00 UTC 2012
Sun Mar 25 12:00:00 UTC 2012
Sun Mar 25 13:00:00 UTC 2012
Sun Mar 25 14:00:00 UTC 2012
Sun Mar 25 15:00:00 UTC 2012
Sun Mar 25 16:00:00 UTC 2012
Sun Mar 25 17:00:00 UTC 2012
Sun Mar 25 18:00:00 UTC 2012
Sun Mar 25 19:00:00 UTC 2012
Sun Mar 25 20:00:00 UTC 2012
Sun Mar 25 21:00:00 UTC 2012
Sun Mar 25 22:00:00 UTC 2012
Sun Mar 25 23:00:00 UTC 2012

but in the database there are these:

in the database

È stato utile?

Soluzione

This is a "feature" of JDBC, not of Hibernate. Consequently you can change this behaviour in the jdbc options (jdbc connect string in hibernate.cfg.xml) and not in the Hibernate options. By default the date values are always saved in the time zone of the client application (and not in the time zone of the database, as it seems to be more logic). MySQL for example knows a jdbc connect option which forces the database to store the date values always in UTC. I don't know if H2 knows such an option, might be not.

In your example the 25th March was the first day with daylight time in that your. 25th March 02:00 didn't exist in your time zone, that's why you don't find it in the database.

If you don't want an option in the connect string (which has the disadvantage it might not be available on all databases) there are three possibilities how to go around the problem:

  1. Before inserting and after reading you do the time zone conversation in your program. For this additionally to your normal getter get/setMyTime() you write an extra getter and setter only for Hibernate get/setHibernateMyTime(), where you do the time zone conversion and which you use in the mapping files or in the annotations. For the time zone conversion you can use TimeZone.getOffset().

  2. Use Strings instead of dates. In this case you don't need to do the time zone conversion, but you have to convert strings into dates and vice versa.

  3. Run the application with UTC as local time. This has disadvantages if the local time of the user is needed anywhere, for example in the user interface.

We did solution 1. in our application.

Altri suggerimenti

As mentioned by Johanna, there are several options how to handle this time zone shift issue. There is also an article explaining the problem in a more detailed way, providing more examples and solutions.

As far as the option number 1 from the previous answer is considered and you don't want to write all the code yourself, you can use a small open source library DbAssist . It maps the java.util.Date and java.util.Timestamp into a custom UtcDateType, which internally overrides setters and getters so that it treats dates in the DB as of UTC timezone, whenever read or write to the database. It is a convenient solution, since you don't have change your entity classes at all.

All you have to do is add the dependency (replace 5.2.2 with your Hibernate version):

<dependency>
    <groupId>com.montrosesoftware</groupId>
    <artifactId>DbAssist-5.2.2</artifactId>
    <version>1.0-RELEASE</version>
</dependency>

Then apply the fix as explained in the installation guide on the project's github. I am not copying it here, because it differs depending on whether you use JPA Annotations or HBM files to map your entity fields; it is a simple one-liner setup though.

Can you explain the data structure of your table? Are you using DATETIME or TIMESTAMP for that column?

As per the MySQL official documentation – MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. It uses the current time zone of the JDBC connection for this conversion.

This behaviour is strange but correct, "Sun Mar 25 02:00:00" doesn't exists in your time zone (probably Center European). If you need to save that date you could create your column as DATETIME.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top