jpa Mapping time and date


Example

Time and date come in a number of different types in Java: The now historic Date and Calendar, and the more recent LocalDate and LocalDateTime. And Timestamp, Instant, ZonedLocalDateTime and the Joda-time types. On the database side, we have time, date and timestamp (both time and date), possibly with or without time zone.

Date and time before Java 8

The default mapping for the pre-Java-8 types java.util.Date, java.util.Calendar and java.sql.Timestamp is timestamp in SQL; for java.sql.Date it is date.

@Entity
class Times {
    @Id
    private Integer id;

    @Basic
    private Timestamp timestamp;

    @Basic
    private java.sql.Date sqldate;

    @Basic
    private java.util.Date utildate;

    @Basic
    private Calendar calendar;
}

This will map perfectly to the following table:

CREATE TABLE times (
    id integer not null,
    timestamp timestamp,
    sqldate date,
    utildate timestamp,
    calendar timestamp
)

This may not be the intention. For instance, often a Java Date or Calendar is used to represent the date only (for date of birth). To change the default mapping, or just to make the mapping explicit, you can use the @Temporal annotation.

@Entity
class Times {
    @Id
    private Integer id;

    @Temporal(TemporalType.TIME)
    private Date date;

    @Temporal(TemporalType.DATE)
    private Calendar calendar;
}

The equivalent SQL table is:

CREATE TABLE times (
    id integer not null,
    date time,
    calendar date
)

Note 1: The type specified with @Temporal influences DDL generation; but you can also have a colum of type date map to Date with just the @Basic annotation.

Note 2: Calendar cannot persist time only.

Date and time with Java 8

JPA 2.1 does not define support for java.time types provided in Java 8. The majority of JPA 2.1 implementations offer support for these types however, though these are strictly speaking vendor extensions.

For DataNucleus, these types just work out of the box, and offers a wide range of mapping possibilities, coupling in with the @Temporal annotation.

For Hibernate, if using Hibernate 5.2+ they should work out of the box, just using the @Basic annotation. If using Hibernate 5.0-5.1 you need to add the dependency org.hibernate:hibernate-java8. The mappings provided are

  • LocalDate to date
  • Instant, LocalDateTime and ZonedDateTime to timestamp

A vendor-neutral alternative would also be to define a JPA 2.1 AttributeConverter for any Java 8 java.time type that is required to be persisted.