JPA使用ZoneOffset存储OffsetDateTime

JPA使用ZoneOffset存储OffsetDateTime,第1张

JPA使用ZoneOffset存储OffsetDateTime

//编辑:我更新了答案以反映JPA 2.1版和2.2版之间的差异。

//编辑2:添加了JPA 2.2规范链接


JPA 2.1的问题

JPA v2.1不知道Java
8类型,并将尝试对提供的值进行字符串化。对于LocalDateTime,Instant和OffsetDateTime,它将使用toString()方法并将相应的字符串保存到目标字段。

也就是说,您必须告诉JPA如何将您的值转换为相应的数据库类型,例如

java.sql.Date
java.sql.Timestamp

实施并注册

AttributeConverter
界面以使其工作。

看到:

  • https://stuetzpunkt.wordpress.com/2015/03/15/persisting-localdate-with-jpa-2-1/
  • http://www.adam-bien.com/roller/abien/entry/new_java_8_date_and

当心亚当·比恩(Adam Bien)的错误实现:必须首先对LocalDate进行分区。

使用JPA 2.2

只是不要创建属性转换器。它们已经包括在内。

//更新2:

您可以在此处的规范中看到这一点:JPA 2.2 spec。滚动到最后一页以查看时间类型。

如果使用jpql表达式,请确保使用Instant对象,并在PDO类中也使用Instant。

例如

// query does not make any sense, probably.query.setParameter("createdOnBefore", Instant.now());

这样很好。

使用
java.time.Instant
代替其他格式

无论如何,即使您具有ZonedDateTime或OffsetDateTime,从数据库读取的结果也将始终为UTC,因为数据库存储的是即时时间,而与时区无关。
时区实际上只是显示信息(元数据)

因此,我建议改为使用

Instant
它,并且仅在需要时将其转换为“区域”或“偏移时间”类。要恢复给定区域或偏移量的时间,请将区域或偏移量分别存储在其自己的数据库字段中。

JPQL比较将与此解决方案一起使用,只需始终保持即时 *** 作即可。

PS:我最近与一些Spring员工进行了交谈,他们还同意,除了Instant之外,您再也不会坚持任何其他方法。只有一个瞬间是特定的时间点,然后可以使用元数据进行转换。

使用复合值

根据JPA 2.2规范,未提及Compositevalues。这意味着,他们没有将其纳入规范中,并且此时您不能将单个字段持久保存到多个数据库列中。搜索“复合”,仅看到与ID相关的提及。

但是,正如此答案的注释中所述,Hibernate可能能够做到这一点。

示例实施

我创建此示例时牢记以下原则:为扩展而打开,为修改而关闭。在此处阅读有关此原则的更多信息:Wikipedia上的开放/封闭原则。

这意味着,您可以将当前字段保留在数据库中(时间戳记),并且只需要添加其他列即可,这不会有任何问题。

另外,您的实体可以保留OffsetDateTime的设置方法和获取方法。内部结构应该与调用者无关。这意味着,此建议完全不会损害您的api。

一个实现可能看起来像这样:

@Entitypublic class UserPdo {  @Column(name = "created_on")  private Instant createdOn;  @Column(name = "display_offset")  private int offset;  public void setCreatedOn(final Instant newInstant) {    this.createdOn = newInstant;    this.offset = 0;  }  public void setCreatedOn(final OffsetDateTime dt) {    this.createdOn = dt.toInstant();    this.offset = dt.getOffset().getTotalSeconds();  }  // derived display value  public OffsetDateTime getCreatedonOnOffset() {    ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(this.offset);    return this.createdOn.atOffset(zoneOffset);  }}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5163221.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-18
下一篇 2022-11-18

发表评论

登录后才能评论

评论列表(0条)

保存