hibernate 4 and joda-time

Solution 1:

A distinct paucity of documentation, means it might be helpful for me to write down the steps required for integration. Make sure your libraries are up to date.

You'll need : [assuming you already have hibernate4]

Latest version of joda-time

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.0</version>
</dependency>

and usertype lib

<dependency>
    <groupId>org.jadira.usertype</groupId>
    <artifactId>usertype.core</artifactId>
    <version>3.0.0.CR1</version>
</dependency>

Then use the following in entity classes (doesn't have to be LocalDateTime, could be any of the persisted classes available) :

import org.joda.time.LocalDateTime;

and for column definition:

@Column(name="updated", nullable = false)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime updated;

Solution 2:

I'll add this as a separate answer since it's in my opinion important information for anyone upgrading to Hibernate 4, and in need of migrating to using jadira's persistent temporal types. This page is highly ranked in google search results for hibernate 4 and jodatime, so I'll add it here. (For a separate discussion of this issue, see: Joda time DateTime incorrectly stores in database)

If you are in a timezone other than UTC, an important piece of configuration is needed in order to get the same behaviour as you would with a joda-time hibernate-support type. The way jadira's temporal types work by default, is through converting all values to the UTC timezone before persisting to the database, and converting back to the system's timezone when loading the values from the database.

I got burned by this after upgrading, when I had a lot of timestamps with my exact timezone in the database (UTC+1 (+2 when summertime)). When loaded after upgrading to Hibernate 4, 1 or 2 hours (depending on whether or not the timestamp was during summer time) was added to the value in the database, which meant that all existing timestamps were presented erroneously. Further, new timestamp values were stored in the database with UTC timezone, leading them to appear correctly in the application, but wrong in the database. All in all, a hot mess of timezones and timestamps.

So, in order to get the same behaviour as with joda-times hibernate-support (the datetime being persisted being of the timezone of the server in question, and the timestamps in the database being the same as what is being loaded into the application), the following properties must be added to the JPA/Hibernate configuration (in my case, hibernate.properties):

jadira.usertype.autoRegisterUserTypes=true
jadira.usertype.databaseZone=jvm
jadira.usertype.javaZone=jvm

This will make sure that the timestamps in the database will be of the same timezone as that of the application, which in turn will be the timezone of the jvm (in most cases the clock of the application server).

Also, from what I understand, the autoRegisterUserTypes-property removes the need for the @Type-annotation for a selection of common types, among them the Jodatime-types DateTime and LocalDate.