Envers inserts erroneous audit entries for many-to-many relation if using `global_with_modified_flag`

Description

If using the config option global_with_modified_flag, envers creates erronous audit entries for ManyToMany relations in certain cases.

Suppose EntityA and EntityB are related via a ManyToMany relation and EntityA is the owning side of the relation. In this case I can remove an EntityB from the relation, persist the EntityA and the relation is updated correctly. If envers is configured with `global_with_modified_flag, it creates 3 audit entries, one for the relation, one for the owning and one for the owned side. The audit entry for the owned side does not contain any data except for id, rev, revtype and the *_mod fields. The _mod field that corresponds to the relation is set to true like it is expected. All other fields are null.

I would expect that all other fields are filled with the current values.

I wrote a reproducer for this problem, the last assert fails:

If anyone can help me with a workaround for this, I would be very thankful.

Activity

Show:

Chris Cranford August 10, 2022 at 5:22 PM

As explained on Zulip, the issue in this situation is the use of getReference() versus find().

In order for Envers to perform proper diff analysis on entity state, the entity must be loaded fully into the PersistenceContext. When using getReference(), the entity’s full state isn’t loaded by ORM and therefore only the primary key fields are available. Envers also does not lazily load this state because this can create other cascading concerns during the listener invocation. So we ultimately rely on the user to guarantee the entity’s state is loaded so the right audit state gets persisted.

You can workaround and avoid this by using EntityManager#find() rather than EntityManager#getReference().

Won't Do

Details

Assignee

Reporter

Components

Affects versions

Priority

Created August 10, 2022 at 10:45 AM
Updated August 10, 2022 at 5:22 PM
Resolved August 10, 2022 at 5:22 PM