Envers - 将新元素添加到 EntityListener @PreUpdate 中的 oneToMany 集合
Envers - add new element to oneToMany collection in EntityListener @PreUpdate
我们有以下实体层次结构和一个 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);
...
}
}
在实体侦听器中,我们想将新的 B 实体添加到 A 实体集合中。但是在保存 A 之后,envers 并没有在 B 审计中为新的 B 实例创建审计记录 table。
除新的 B 实例外,所有其他更改都有审计记录。
我们做错了什么?可以通过这种方式创建新的 B 实例吗?
根据 JPA 规范 2.1:
In general, the lifecycle method of a portable application should not invoke EntityManager or query operations, access other entity instances, or modify relationships within the same persistence context.
这里的要点是,通过添加新的 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 );
}
}
如果您仅使用 Hibernate 进行测试而不使用审计,您会注意到 B
的新实例在 @PreUpdate
的生命周期回调中创建时甚至不会持久化。
因此,如果 Hibernate 不允许这样的用例,Envers 甚至无法检测状态变化并执行必要的收集工作单元。
我们有以下实体层次结构和一个 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);
...
}
}
在实体侦听器中,我们想将新的 B 实体添加到 A 实体集合中。但是在保存 A 之后,envers 并没有在 B 审计中为新的 B 实例创建审计记录 table。 除新的 B 实例外,所有其他更改都有审计记录。
我们做错了什么?可以通过这种方式创建新的 B 实例吗?
根据 JPA 规范 2.1:
In general, the lifecycle method of a portable application should not invoke EntityManager or query operations, access other entity instances, or modify relationships within the same persistence context.
这里的要点是,通过添加新的 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 );
}
}
如果您仅使用 Hibernate 进行测试而不使用审计,您会注意到 B
的新实例在 @PreUpdate
的生命周期回调中创建时甚至不会持久化。
因此,如果 Hibernate 不允许这样的用例,Envers 甚至无法检测状态变化并执行必要的收集工作单元。