Add support for Java 8 date and time types (JSR-310)

Description

Implement support for the new Java 8 temporal Java types (JSR 310).

The initial implementation defines the following Types:

  • org.hibernate.type.DurationType - Maps a java.time.Duration to a SQL BIGINT (Long) representing the duration-in-nanoseconds.

  • org.hibernate.type.InstantType - Maps a java.time.Instant to a SQL TIMESTAMP

  • org.hibernate.type.LocalDateTimeType - Maps a java.time.LocalDateTime to a SQL TIMESTAMP

  • org.hibernate.type.LocalDateType - Maps a java.time.LocalDate to a SQL DATE

  • org.hibernate.type.LocalTimeType - Maps a java.time.LocalTime to a SQL TIME

  • org.hibernate.type.OffsetDateTimeType - Maps a java.time.OffsetDateTime to a SQL TIMESTAMP

  • org.hibernate.type.OffsetTimeType - Maps a java.time.OffsetTime to a SQL TIME

  • org.hibernate.type.ZonedDateTimeType - Maps a java.time.ZonedDateTime to a SQL TIMESTAMP

As this relies on Java 8 and Hibernate still maintains compatibility back to Java 6, a new module hibernate-java8 was added to isolate the Java 8 compatibility to just these classes. We will fold the classes from this module into hibernate-core once we baseline one Java 8.


Original request

It would be cool to be able to persist the date time types newly introduced in Java 8 in a reasonable way. Currently the values are persisted as blobs effectively.

There are already a user type implementations for the backport project of JSR-310 but they unfortunately don't work with the types from the java.time package. The support has also been requested in the user forums.

Activity

Show:

Mirko Mittmann April 13, 2015 at 12:56 PM

Hi,

i'm new to this, but i have something for the "HHH000072: Duplicate joins for class:".

I've tested the new version. In the class "org.hibernate.boot.internal.InFlightMetadataCollectorImpl" was this message thrown,
after using following code:
MetadataSources metadataSources = new MetadataSources(standardServiceRegistry).addAnnotatedClass(....class).addAnnotatedClass(....class).addAnnotatedClass(....class);
MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder();
Metadata metadata = metadataBuilder.build();

After "metadataBuilder.build()" my 3 classes from addAnnotatedClass where duplicated. I saw this in the method "imports" from "MetadataImpl".

Hope it could help for resolving.

PS: If i had made a mistake for posting this here, please moved or delete it.

JB Nizet March 26, 2015 at 5:31 PM
Edited

By Spring integration, I mean that I use spring-orm and spring-data-jpa in the app to create the EMFactory, handle declarative transactions, discover entities by classpath scanning, etc., and it worked fine. I wouldn't have been surprised, given the major version change, if Spring had a problem with the new version. It appeared that it didn't have any. That was not possible when switching from hibernate 3 to hibernate 4, and Spring had to rewrite many classes for hibernate 4 support.

I indeed let Hibernate set everything up. I just changed the hibernate version number in my gradle dependencies, added the hibernate-java8 dependency, removed the jadira dependency, and everything went fine. A typical mapped Instant field looks like this:

private Instant registrationDate;

Regarding the last question, it's a tough one. I made that choice based on this SO answer and the linked blog post.
Given that JDBC uses the default timezone by default when setting a timestamp (unless you use the method with an additional Calendar argument, using a timestamptz is much safer, because it pays attention to the timezone, meaning that no conversion needs to be done at all, and no Calendar needs to be passed to have the correct value stored in UTC.

numéro6 March 26, 2015 at 5:10 PM

Using Hibernate 5 snapshot breaks ToPIA (jenkins build), I won't be able to provide a feedback soon disappointed face (too bad!) We have to solve all those compatibility break first.

Steve Ebersole March 26, 2015 at 4:56 PM

Awesome, thanks for trying it out! I have noticed that occasionally too wrt HHH000072, but have been so heads down trying to get ready for the 5.0.0 Beta release that I have not yet had time to look closer. I will get to it.

Out of curiosity, what is "Spring integration"?

Did you just let Hibernate set everything up and let it pick the types based on the attribute's Java type? That's the main thing here. Once that all happens, schema generation and other stuff will just flow. Although I will say that for schema export etc Hibernate does not generally use "with timezone" variants of date/time. Which brings me too...

There is a discussion on the dev mailing list right now wrt these types and handling timezones. IMO we really ought to be leveraging the power of these new classes and converting everything to UTC (if not already in UTC) for storing. And then reading back in UTC. My personal belief is that "this idea of trying to store and handle dates in different timezones is silly, and more importantly that it is asking for trouble". If anyone has strong opinions, they might want to chime in on that email thread.

JB Nizet March 26, 2015 at 4:18 PM

I just tested it on quizzie.io, which currently uses jadira: all tests pass, and the app runs smoothly.

Some notes and caveats:

  • the only java.time type used in the entities is java.time.Instant

  • the database schema is not generated by Hibernate, so I didn't test schema generation.

  • database used is PostgreSQL 9.3, column type is timestamptz

  • Spring integration works fine

  • unrelated: I get a warning for *every* entity that I didn't get with Hibernate 4, which is not very clear and seems like a false positive: `WARN o.h.b.i.InFlightMetadataCollectorImpl - HHH000072: Duplicate joins for class: ...`. Note that I get this warning even for entities that have no association at all with any other entity.

Fixed

Details

Assignee

Reporter

Labels

Time tracking

9.75h logged

Components

Fix versions

Priority

Created January 9, 2014 at 11:08 AM
Updated February 23, 2016 at 10:47 AM
Resolved March 25, 2015 at 8:36 PM