【问题标题】:How to persist OffsetTime and OffsetDateTime with JPA and Hibernate?如何使用 JPA 和 Hibernate 持久化 OffsetTime 和 OffsetDateTime
【发布时间】:2015-05-26 11:59:39
【问题描述】:

如何将 Java 8 OffsetTimeOffsetDateTime 与 Hibernate 保持为正确的 SQL 类型(TIME_WITH_TIMEZONETIMESTAMP_WITH_TIMEZONE)?我在a blog 中使用EnhancedUserTypes 找到了LocalTimeLocalDateTime 的解决方案。

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

【问题讨论】:

  • 参见HHH-8844(Hibernate 错误数据库)——显然这仍然不是 Hibernate 的标准功能。 (关于该问题的 cmets 包含指向您已经找到的博客的链接......)。

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


【解决方案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") 公共静态类 DateTimeEntity { @ID 私人整数 id; @Column(name = "duration_value") 私人持续时间持续时间= Duration.of(20,ChronoUnit.DAYS); @Column(name = "instant_value") 私人 Instant Instant = Instant.now(); @Column(name = "local_date") 私人 LocalDate localDate = LocalDate.now(); @Column(name = "local_date_time") 私有 LocalDateTime localDateTime = LocalDateTime.now(); @Column(name = "local_time") 私有 LocalTime localTime = LocalTime.now(); @Column(name = "offset_date_time") 私人 OffsetDateTime offsetDateTime = OffsetDateTime.now(); @Column(name = "offset_time") 私人 OffsetTime offsetTime = OffsetTime.now(); @Column(name = "zoned_date_time") 私有 ZonedDateTime zonedDateTime = ZonedDateTime.now(); //为简洁起见省略了getter和setter }

关联的数据库表将是:

创建表 DateTimeEntity ( id 整数不为空, duration_value bigint, 即时值时间戳, local_date 日期, local_date_time 时间戳, local_time 时间, offset_date_time 时间戳, offset_time 时间, zoned_date_time 时间戳, 主键(id) )

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

【讨论】:

    【解决方案2】:

    从 2.2 版开始,JPA 支持映射 Java 8 日期/时间 API,例如 LocalDateTimeLocalTimeLocalDateTimeTimeOffsetDateTimeOffsetTime

    此外,即使使用 JPA 2.1,Hibernate 5.2 默认也支持所有 Java 8 日期/时间 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()
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-09
      • 2013-11-12
      • 1970-01-01
      • 2016-02-20
      • 2011-04-02
      • 1970-01-01
      • 2014-12-04
      • 1970-01-01
      相关资源
      最近更新 更多