Envers - add new element to oneToMany collection in EntityListener @PreUpdate

1k views Asked by At

We have the following entity hierarchy and a 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);
    ...
  }

}

In the entity listener we would like to add new B entity to the A entity collection. But after saving A, the envers didn't create audit record for new B instance in B audit table. Every other changes has audit records except new B instance.

What do we wrong? It is possible to create new instance of B in this way?

1

There are 1 answers

1
Naros On BEST ANSWER

Per JPA Spec 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.

The point here is that by adding a new B and relating it to A means you're modifying the relationships between entities, albeit a new entity B.

So taking the following code:

@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 );
  }
}

If you test this with just Hibernate and no auditing, you'd notice that the new instance of B is not even persisted when its created within the lifecycle callback of @PreUpdate.

So if Hibernate doesn't permit such a use case, there is no way which Envers would even be capable of detecting the state changes and performing the necessary collection work units.