保持OffsetTime和OffsetDateTime

时间:2015-03-23 13:14:52

标签: java hibernate java-8 hibernate-mapping java-time

如何将Java 8 OffsetTimeOffsetDateTime与Hibernate一起作为正确的SQL类型(TIME_WITH_TIMEZONETIMESTAMP_WITH_TIMEZONE)来维护?我在a blog中使用LocalTime找到了LocalDateTimeEnhancedUserType的解决方案。

用户类型如何用于偏移数据?

2 个答案:

答案 0 :(得分:2)

由于这是一个非常常见的问题,所以此答案基于this article,我写了用JPA映射日期和时间戳的最佳方法。

从2.2版开始,JPA支持映射Java 8 Date/Time API,例如LocalDateTimeLocalTimeLocalDateTimeTimeOffsetDateTimeOffsetTime。 / p>

此外,即使使用JPA 2.1,Hibernate 5.2默认也支持所有Java 8 Date / Time API。

在Hibernate 5.1和5.0中,您必须添加hibernate-java8 Maven依赖项。

因此,假设我们具有以下Notification实体:

@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
}

请注意,createdOn属性是OffsetDateTime Java对象,而clockAlarmOffsetTime类型。

坚持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生成正确的SQL INSERT语句:

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

在获取Notification实体时,我们可以看到OffsetDateTimeOffsetTime 是从数据库中正确提取的:

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()
);

答案 1 :(得分:1)

从Hibernate开始,ORM 5.3实现了JPA 2.2标准。

JPA 2.2规范说,现在支持以下Java 8类型:

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

因此,您可以对表使用timestamp作为示例:

您拥有的实体


    @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
    }

关联的数据库表为:


    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)
    )

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