Hibernate Envers ValidityAuditStrategy throws a "Cannot update previous revision for entity" exception


#1

I created a sample project & done CRUD operations. Now I added & enabled envers, set ValidityAuditStrategy. Now on trying to update existing table rows, envers throwing exception as below. Is this an Envers bug? How to go ahead for this case?

"ERROR: HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.RuntimeException: Cannot update previous revision for entity OfficeAddress_AUD and id 1
org.hibernate.AssertionFailure: Unable to perform beforeTransactionCompletion callback
	at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:905)
	at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:481)
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2353)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)"

#2

Try to replicate it with this test case template.


#3

The ValidityAuditStrategy expects that a prior change data capture (CDC) row exists with the same primary key where the REV_END column is NULL. If no row exists with this requirement when an update to an entity occurs, this strategy will throw this exception because the prior row state cannot be updated correctly to reflect the proper chain of REV_END values.

So why would the prior row not exist?

One common mistake is to allow insertion of audited data through means that completely bypass the event system of Hibernate. Examples of this include direct SQL manipulation, native-queries, or even the use of Hibernate’s Stateless session.

Another common reason this can happen is when Envers is enabled on an existing database with data while using the ValidityAuditStrategy implementation. In short, what happens is future changes get tracked but because no prior INSERT operation was ever audited, the strategy asserts with this failure.

Its generally accepted practice that if you intend to enable Envers on an existing legacy database, make sure that you seed the audit tables after they’ve been generated before manipulating the entities. This makes sure that the seeded data represents the current INSERT snapshot of all your audited data prior to future UPDATE changes being applied.