Envers-在EntityListener @preupdate中的OneTomany Collection中添加新元



我们有以下实体层次结构和EntityListener

@Entity
@EntityListeners(value = DummyListener.class)
@Audited
public class A {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "a", fetch = FetchType.LAZY, orphanRemoval = true)
  @Fetch(FetchMode.SELECT)
  private Set<B> bs = new LinkedHashSet<B>(0);
}
@Entity
@Audited
public class B {
  @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  @JoinColumn(name = "a_id", nullable = false)
  private A a;
}
public class DummyListener {
  @PreUpdate
  public void beforeUpdate(A entity) {
    entity.set...(...);
    ...
    B old = entity.getBs().iterator().next();
    old.set...(...);
    ...
    B b = new B();
    b.setA(entity);
    entity.getBs().add(b);
    ...
  }

}

在实体侦听器中,我们想为A实体集合添加新的B实体。但是保存A后,Envers没有在B审核表中为新B实例创建审核记录。其他所有更改都有审核记录,除了新的B实例。

我们错了?可以以这种方式创建B的新实例?

per jpa spec 2.1:

通常,便携式应用程序的生命周期方法不应调用EntityManager或查询操作,访问其他实体实例或在相同持久性上下文中修改关系。

这里的重点是,通过添加新的B并将其关联到A意味着您正在修改实体之间的关系,尽管是一个新的实体B

因此,请使用以下代码:

@PreUpdate
public void onPreUpdate(Object object) {
  if ( object instanceof A ) {
    final A a = (A) object;
    final B b = new B();
    b.setA( a );
    a.getBs().add( b );
  }
}

如果您只需冬眠而没有审核测试,您会注意到,当B的新实例在@PreUpdate的生命周期回调中创建时,甚至没有持续存在。

因此,如果Hibernate不允许这样的用例,那么Envers甚至无法检测状态更改并执行必要的收集工作单位。

最新更新