Hibernate 5: How to persist LocalDateTime & Co with Hibernate


Take your skills to the next level!

The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.


The Date and Time API, introduced in Java 8, finally replaced the old java.util.Date. It’s much easier to use and finally offers separate classes representing date, date with time, and only time information. That not only improves your business code but also makes it easier to use them as entity attributes. At least if you’re using the correct version of JPA and/or Hibernate.

You have 3 options if you want to use the right JDBC types when you persist classes of the Date and Time API:

  • If you’re using JPA in a version < 2.2 or Hibernate in a version < 5, You can implement a JPA AttributeConverter and convert the Java 8 class into one that is supported by Hibernate. I described this in detail in How to persist LocalDate and LocalDateTime with JPA. This approach does not use any Hibernate-specific APIs and is portable to other JPA implementations, but it is a little complicated.
  • You can use JPA in a version >= 2.2. It supports some of the classes of the Date and Time API as basic attribute types.
  • You can use the Hibernate-specific Java 8 support which was introduced with Hibernate 5. It supports a few more data types than JPA 2.2.

Java 8 Support in Hibernate 5

One of the features added with Hibernate 5 is the support of Java 8 classes like the Date and Time API.

The Java 8 support was initially shipped in a separate jar file called hibernate-java8.jar, which you needed to add to the classpath of your application. Since Hibernate 5.2, it’s part of the core distribution and the additional jar file is no longer required.

<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-java8</artifactId>
	<version>5.1.0.Final</version>
</dependency>

JDBC Mappings

Hibernate maps the classes of the Date and Time API to the corresponding JDBC types. The following table shows an overview of the supported classes and their JDBC mapping.

Java typeJDBC type
java.time.DurationBIGINT
java.time.InstantTIMESTAMP
java.time.LocalDateTimeTIMESTAMP
java.time.LocalDateDATE
java.time.LocalTimeTIME
java.time.OffsetDateTimeTIMESTAMP
java.time.OffsetTimeTIME
java.time.ZonedDateTimeTIMESTAMP

Date and Time API Classes As Entity Attributes

Hibernate supports the classes of the Date and Time API as BasicTypes. This provides the main advantage that you don’t have to add any additional annotations. Not even the @Temporal annotation which you currently add to each java.util.Date attribute.

Hibernate gets all required information from the type of the attribute. You can see an example of an entity with attributes of type LocalDate, LocalDateTime, and Duration in the following code snippet.

@Entity
public class MyEntity {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", updatable = false, nullable = false)
	private Long id;
	
	@Column
	private LocalDate date;
	
	@Column
	private LocalDateTime dateTime;
	
	@Column
	private Duration duration;
	
	...
}

You can then use these attributes in the same way as any other attributes in your Java code.

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

MyEntity e = new MyEntity();
e.setDate(LocalDate.now());
e.setDateTime(LocalDateTime.now());
e.setDuration(Duration.ofDays(2));

em.persist(e);

And as you can see in the following screenshot, Hibernate persists them with the right JDBC data type instead of the blob it uses without the hibernate-java8.jar.

Conclusion

Hibernate started supporting classes of the Date and Time API in version 5. Hibernate 5.0.x and Hibernate 5.1.x were still based on Java 7 and required an additional jar file to support any Java 8 features. But since Hibernate 5.2, the support for the Date and Time API is part of the hibernate-core module.

Hibernate handles the classes of the Date and Time API as BasicTypes. This makes them even easier to use than the old java.util.Date. You no longer have to add any additional annotations to define the JDBC type to which you want to map it. And Hibernate also supports a few more date types than required by the JPA specification.

13 Comments

  1. Avatar photo Arthur Eduardo Moura says:

    Hello, thank you!! Your post helped me a lot.

  2. could you please confirm below query’s
    1.hibernate 5.x support from which version of spring ?
    2.left joins, right join Query’s is it work with out relations?

    1. Avatar photo Thorben Janssen says:

      Hi,
      I don’t know exactly when Spring Data JPA started to support Hibernate 5. Please take a look at the documentation.
      JPQL supports only left joins and inner joins.

  3. Avatar photo Puspender says:

    Hello Thorben,
    In my case, the LocalDateTime and LocalDate persisted even without using the hibernate-java8 dependency. I am using the Spring-data-jpa and hibernate as it’s implementation. Is it handled by Spring?

  4. Avatar photo RichardWang says:

    this really helps. thanks a lot

  5. Avatar photo Rafael alvaro Ruiz tabares says:

    Thanks for this post

    1. Avatar photo Thorben Janssen says:

      Thanks, I updated the post.

  6. Hi Thorben,

    good post!

    I’m curious about what happens behind the scene. A LocalDateTime for instance has no time zone information. Will Hibernate use system default for the Timstamp? And if using the ZonedDateTime, will Hibernate use the associated Instant object?

    Kind regards,
    Henrik

  7. AttributeConverter cannot be used when the field is a primary key (nor part of a compound PK)

    if the LocalDate field is in fact a primary key, when running in wildlfy 10, will using this hibernate specific feature still work?

    1. Avatar photo Thorben Janssen says:

      Yes, it will work because Hibernate now supports LocalDate as native attribute. So, no AttributeConverter is needed.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.