简体   繁体   中英

How to persist OffsetTime and OffsetDateTime with JPA and Hibernate

How can I persist Java 8 OffsetTime and OffsetDateTime with Hibernate as proper SQL types ( TIME_WITH_TIMEZONE and TIMESTAMP_WITH_TIMEZONE )? I found a solution for LocalTime and LocalDateTime using EnhancedUserType s in a blog .

How would the user types be for offset data?

From Hibernate ORM 5.3 implements the JPA 2.2 standard.

The JPA 2.2 specification says that the following Java 8 types are now supported:

  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime
  • java.time.OffsetTime
  • java.time.OffsetDateTime

So, you can use timestamp for the table as example:

Entity you have:

@Entity(name = "DateTimeEntity")
    public static class DateTimeEntity {

            @Id
            private Integer id;

            @Column(name = "duration_value")
            private Duration duration = Duration.of( 20, ChronoUnit.DAYS );

            @Column(name = "instant_value")
            private Instant instant = Instant.now();

            @Column(name = "local_date")
            private LocalDate localDate = LocalDate.now();

            @Column(name = "local_date_time")
            private LocalDateTime localDateTime = LocalDateTime.now();

            @Column(name = "local_time")
            private LocalTime localTime = LocalTime.now();

            @Column(name = "offset_date_time")
            private OffsetDateTime offsetDateTime = OffsetDateTime.now();

            @Column(name = "offset_time")
            private OffsetTime offsetTime = OffsetTime.now();

            @Column(name = "zoned_date_time")
            private ZonedDateTime zonedDateTime = ZonedDateTime.now();

            //Getters and setters omitted for brevity
    }

Associated database table would be:

create table DateTimeEntity
    (
        id                  integer not null,
        duration_value      bigint,
        instant_value       timestamp,
        local_date          date,
        local_date_time     timestamp,
        local_time          time,
        offset_date_time    timestamp,
        offset_time         time,
        zoned_date_time     timestamp,
        primary key (id)
    )

Reference: http://in.relation.to/2018/02/20/java8-date-time-mapping/

Since version 2.2, JPA offers support for mapping Java 8 Date/Time API, like LocalDateTime , LocalTime , LocalDateTimeTime , OffsetDateTime or OffsetTime .

Also, even with JPA 2.1, Hibernate 5.2 supports all Java 8 Date/Time API by default.

In Hibernate 5.1 and 5.0, you have to add the hibernate-java8 Maven dependency.

So, let's assume we have the following Notification entity:

@Entity(name = "Notification")
@Table(name = "notification")
public class Notification {

    @Id
    private Long id;

    @Column(name = "created_on")
    private OffsetDateTime createdOn;

    @Column(name = "notify_on")
    private OffsetTime clockAlarm;

    //Getters and setters omitted for brevity
}

Notice that the createdOn attribute is a OffsetDateTime Java object and the clockAlarm is of the OffsetTime type.

When persisting the Notification :

ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules()
    .getOffset(LocalDateTime.now());

Notification notification = new Notification()
    .setId(1L)
    .setCreatedOn(
        LocalDateTime.of(
            2020, 5, 1,
            12, 30, 0
        ).atOffset(zoneOffset)
    ).setClockAlarm(
        OffsetTime.of(7, 30, 0, 0, zoneOffset)
    );

entityManager.persist(notification);

Hibernate generates the proper SQL INSERT statement:

INSERT INTO notification (
    notify_on, 
    created_on, 
    id
) 
VALUES (
    '07:30:00', 
    '2020-05-01 12:30:00.0', 
    1
)

When fetching the Notification entity, we can see that the OffsetDateTime and OffsetTime are properly fetched from the database:

Notification notification = entityManager.find(
    Notification.class, 1L
);

assertEquals(
    LocalDateTime.of(
        2020, 5, 1,
        12, 30, 0
    ).atOffset(zoneOffset),
    notification.getCreatedOn()
);

assertEquals(
    OffsetTime.of(7, 30, 0, 0, zoneOffset),
    notification.getClockAlarm()
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM