简体   繁体   中英

Java Date in hibernate mapping from DB (timezone issue and daylight savings)

I have read many answers on similar question but still can't understand the whole logic. My aim is to handle date (including time, not just year month etc) inside of my application and consider the daylight savings time shift and server's timezone as well. I am using hibernate and postgresql db. My mistake was to use java.util.Date type for all the dates coming from DB. Soon I realized that it doesn't contain timezone information. Now the question arises, how to use correct Date (daylight and timezone considered)?

What would be the correct way to do it? Using different type of class such as Calendar? Or just leave it as it is but at every place where I use Date I should convert it to local timezone with Calendar for example?

What makes me confused is how the date comes from db into the Date object and if its safe to convert that Date object to Calendar to include timezone etc.?

It is not really true that java.util.Date does not carry a timezone information. By convention it is a UTC timestamp (okay, it is not really because the Javadoc states it skips the leap seconds ).

However, you are quite fine if you assume it is UTC, at least the Calendar.getTime() method does.

Using the Calendar instead of Date within the application logic for building/creating the Date instances is a good first step. Use the Calendar methods setTimeZone to manage the timezone within your application, it will recompute the field values like HOUR_OF_DAY for you.

Hibernate uses JDBC to execute the SQL statements, so it is bound to the possibilities of the JDBC API and the behaviour of the JDBC driver you use and of cause the possibilities of the database.

My experience is that the JDBC drivers and the databases do differ in the Date/Time handling, espacially when it comes to timezone. postgres sql for example has date/time field type with and without timezone. Unfortunatly the types with timezone are not part of the SQL spec., so they are not part of the JDBC spec. and so Hibernate does not support them out of the box.

Long explanation for a short answer: The most common approach to solve this issue is to make sure you always store and load your data from Hibernate with the same timezone. A easy way is using UTC timezone for it, because the Calendar.getTime() method always returns the current time as UTC Date instance, which you may directly pass to Hibernate. Loading values from database, you convert them to Calendar using Calendar.setTime(Date) method.

One way to make sure that your dates (and their timezones) are consistent whenever you read/write to the database is to make sure that you use UTC timezone in your database. As mentioned before, there is a common problem with JDBC, because when it reads a date from the database it by default treats the date as of local JVM timezone. So, if your local JVM timezone is different than the one used in DB, you will face unexpected time zone shifts (for example, when running your application from two locations in different timezones).

There is a nice article explaining the root of the problem here . There is also a small open source library DbAssist which you can use in your project to make sure that JDBC and then Hibernate treat dates from Database as of UTC timezone.

To include the fix, add the following dependency into your POM file:

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

This particular fix works for Hibernate 5.2.2 version, but if you are using any other Hibernate, just refer to this link for the proper fix version. It also includes installation guide, which differs a bit depending on whether you are using HBM files or JPA Annotations (with or without Spring Boot) to map your entity fields. In both cases, applying the fix is just a matter of one line of code .

The good thing about this library (fix) is that you do not have to change anything in your entity classes. Once you add dependency and apply the fix, the java.util.Date fields in entities are considered to be UTC timezone (when write/read from DB).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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