Envers: collection-change audit row is mapped from an uninitialized proxy, writing NULL for every audited property of the related entity

When Envers generates a MOD revision for the far side of a bidirectional collection change (revision_on_collection_change=true, the default), BaseEnversCollectionEventListener passes the raw collection element / owner reference into CollectionChangeWorkUnit without unwrapping Hibernate proxies — unlike the entity-event path, where BaseEnversEventListener#addCollectionChangeWorkUnit unwraps via EntityTools.getTargetFromProxy (HHH-7249).

If the session already holds an uninitialized proxy of the related entity when the collection is processed, the work unit maps the audit row off the proxy wrapper: the property mapper’s reflection field-reads (GetterFieldImpl → raw Field.get) return null for every audited property, so the _AUD MOD row records NULL in every column.

Consequences:

  1. Silent audit corruption (default config): the entity’s history gains a MOD revision claiming all its properties became null.
  2. Hard failure with do_not_audit_optimistic_locking_field=false and a NOT NULL version column in the _AUD schema: the insert binds NULL for the version and rolls back an otherwise-valid entity delete with a constraint violation.

Steps to reproduce

Runnable reproducer: GitHub - apoorvam/envers-collection-change-proxy-repro · GitHub — clone and run mvn test. The single test fails on 7.2.19.Final with expected: <parent> but was: <null>; the README walks through the mechanism in detail.

In short: a Child references the same audited Parent through a lazy @ManyToOne (seeds the uninitialized proxy at em.find(Child)) and an owned bidirectional @ManyToMany; deleting the child fires the collection-remove event whose element resolves to that proxy. Removing either relationship makes the test pass.

Suggested fix

In BaseEnversCollectionEventListener, unwrap the entity reference before constructing CollectionChangeWorkUnit, the same way BaseEnversEventListener#addCollectionChangeWorkUnit does — in both generateBidirectionalCollectionChangeWorkUnits and the owner work units built from event.getAffectedOwnerOrNull() (guarding the null-owner case).

Thanks for the report. Please try to create a reproducer with our test case template and if you are able to reproduce the issue, create a bug ticket in our issue tracker and attach that reproducer.
If you’re eager to contribute your fix idea, please open a pull request directly against the Hibernate ORM repository as well.

@beikov Envers: unwrap proxies in collection-change audit work units by apoorvam · Pull Request #13177 · hibernate/hibernate-orm · GitHub - Made a PR and unable to create a issue in issue tracker.

Please take a look at the following similar reports about not being able to create Jira tickets:

We heard a couple of times from users that it takes a bit of time until newly created accounts are fully activated, so maybe try again the next day.