YouTube video

Hibernate 5: How to persist LocalDateTime & Co with Hibernate

By Thorben Janssen

Date and Time, Mapping

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.


Tags

Date and Time, Mapping


About the author

Thorben is an independent consultant, international speaker, and trainer specialized in solving Java persistence problems with JPA and Hibernate.
He is also the author of Amazon’s bestselling book Hibernate Tips - More than 70 solutions to common Hibernate problems.

Books and Courses

Coaching and Consulting

Tools

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.

  1. 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. 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.

  2. 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?

  3. 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

  4. 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. Yes, it will work because Hibernate now supports LocalDate as native attribute. So, no AttributeConverter is needed.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}