【问题标题】:JPA/Hibernate: how to automatically update fields on entity updateJPA/Hibernate:如何在实体更新时自动更新字段
【发布时间】:2015-11-30 09:08:50
【问题描述】:

我正在使用 Camel 和 JPA 将实体持久保存到 Postgres 数据库。在每个实体中,我都有一个名为“历史”的字段,其中包含给定实体的所有旧值。我正在寻找一种在每次更新操作之前自动填充此字段的方法。 在网上冲浪时,我发现了 JPA 拦截器,但我看到它们用于审计/记录目的。我错了吗? 最好的方法是什么?

【问题讨论】:

  • 您打算如何将更改存储在一列中?
  • @Funtik 这是一个 json 字段,默认由 postgres 处理
  • 我认为你也可以使用数据库触发器。
  • 我希望在应用程序中有更多控制权
  • 你检查Envers了吗?这是在 Hibernate 中创建历史的常用方法。

标签: java hibernate jpa


【解决方案1】:

JPA/Hibernate 拦截器(取决于您使用的版本)是一种方法。审计/日志记录与您想要做的类似,即在实体本身更新(任何属性)时自动更新某些列/属性。请注意,手动更新查询会绕过这些拦截器,因此应该避免这些。

您如何使用这些拦截器取决于您希望如何实现该历史记录功能。如果您通过生成一些字符串/字节表示并将其存储在列中来做到这一点,它应该可以工作。如果您打算创建另一个实体等,您可能必须在拦截器中收集更改/旧值,并在成功提交后存储收集的值。 AFAIK 在调用拦截器时不可能(至少不容易)创建一个新实体。

【讨论】:

  • 感谢您的回复。对于“手动更新查询”,您的意思是直接在数据库上执行的查询(不使用应用程序)?在这种情况下,我可以摆脱它。
  • @dylaniato 我的意思是直接在实体管理器上调用的任何查询(JPQL/HQL 或 SQL)。为了让拦截器工作,你必须让 Hibernate 找出变化并触发查询,至少这是我们迄今为止从测试/实现中学到的。
【解决方案2】:
@Entity
@Table(name = "entities")    
public class Entity {
  ...

  private Date created;
  private Date updated;

  @PrePersist
  protected void onCreate() {
    created = new Date();
  }

  @PreUpdate
  protected void onUpdate() {
    updated = new Date();
  }
}

【讨论】:

    【解决方案3】:

    您可以使用@EntityListeners 并为其提供您的实体侦听器类,您也可以随时重复使用它

    在您的实体侦听器类中,您可以提供带有@PrePersit, @PostPersist, @PreUpdate, @PostUpdate, @PreDelete, @PostDelete 注释的回调方法。这些方法将被自动调用以执行它们各自的操作。

    您可以阅读Spring Data JPA Auditing: Saving CreatedBy, CreatedDate, LastModifiedBy, LastModifiedDate automatically了解更多详情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-16
      • 2018-08-24
      • 1970-01-01
      相关资源
      最近更新 更多