Java 如何使用JPA和Hibernate持久化OffsetTime和OffsetDateTime

Java 如何使用JPA和Hibernate持久化OffsetTime和OffsetDateTime,java,hibernate,java-8,hibernate-mapping,java-time,Java,Hibernate,Java 8,Hibernate Mapping,Java Time,如何使用Hibernate作为适当的SQL类型(TIME\u和TIMESTAMP\u和\u时区)来持久化Java 8OffsetTime和OffsetDateTime?我在中使用EnhancedUserTypes找到了LocalTime和LocalDateTime的解决方案 偏移数据的用户类型如何?来自Hibernate ORM 5.3的用户类型实现了JPA 2.2标准 JPA 2.2规范指出,现在支持以下Java 8类型: java.time.LocalDate java.time.Loca

如何使用Hibernate作为适当的SQL类型(
TIME\u和
TIMESTAMP\u和\u时区
)来持久化Java 8
OffsetTime
OffsetDateTime
?我在中使用
EnhancedUserType
s找到了
LocalTime
LocalDateTime
的解决方案


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

来自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
因此,您可以对表使用
时间戳
,例如:

您拥有的实体:

@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 } @实体(name=“DateTimeEntity”) 公共静态类DateTimeEntity{ @身份证 私有整数id; @列(name=“持续时间值”) 私人持续时间=持续时间(20天); @列(name=“瞬时值”) private Instant Instant=Instant.now(); @列(name=“local\u date”) private LocalDate LocalDate=LocalDate.now(); @列(name=“local\u date\u time”) private LocalDateTime LocalDateTime=LocalDateTime.now(); @列(name=“本地时间”) private LocalTime LocalTime=LocalTime.now(); @列(name=“offset\u date\u time”) private OffsetDateTime OffsetDateTime=OffsetDateTime.now(); @列(name=“offset\u time”) private OffsetTime OffsetTime=OffsetTime.now(); @列(name=“分区日期时间”) private ZonedDateTime ZonedDateTime=ZonedDateTime.now(); //为简洁起见省略了getter和setter } 关联的数据库表将是:

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) ) 创建表DateTimeEntity ( id整数不为空, 持续时间值bigint, 瞬时值时间戳, 本地_日期, 本地日期时间戳, 当地时间, 偏移量\日期\时间戳, 偏移时间, 分区日期时间戳, 主键(id) )
参考资料:

自2.2版以来,JPA提供了对映射Java8日期/时间API的支持,如
LocalDateTime
LocalTime
LocalDateTime
OffsetDateTime
OffsetTime

此外,即使使用JPA2.1,Hibernate5.2默认也支持所有Java8日期/时间API

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

因此,假设我们有以下
通知
实体:

@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对象,
clockAlarm
OffsetTime
类型

持续显示
通知时

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
)
获取
通知
实体时,我们可以看到
OffsetDateTime
OffsetTime
正确地从数据库中获取:

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()
);
请参阅(Hibernate bug数据库)-显然,这仍然不是Hibernate中的标准功能。(关于该问题的评论包含指向您已经找到的博客的链接…)。