Java 如何使用JPA和Hibernate持久化OffsetTime和OffsetDateTime
如何使用Hibernate作为适当的SQL类型(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
TIME\u和TIMESTAMP\u和\u时区)来持久化Java 8OffsetTime
和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中的标准功能。(关于该问题的评论包含指向您已经找到的博客的链接…)。