Mayras
Mayras

Reputation: 3

Discard revision in Hibernate Envers

I don't need to save revision in some cases for entity, but how to handle this way? I want to just skip creation of revision, already reviewed source codes, no chance.

If u try to make DB changes in custom EnversPostInsertEventListenerImpl, for example, make calls in same transaction like that (in onPostInsert):

        PersistedProperty property = dao.findClass(PersistedProperty.class, "where propertyTemplate.id = ? and fileEntry.id = ?",
                propertyTemplate.getId(), f.getId());
        String v = convertObject2String(propertyTemplate, value);
        if (property == null) {
            property = new PersistedProperty(propertyTemplate, v, f);
        } else {
            property.setValue(v);
        }
        dao.merge(property);

Then u will get next exception:

java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
 at java.util.ArrayList$Itr.next(ArrayList.java:851)
 at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
 at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:587)
 at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
 at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
 at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
 at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1435)
 at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
 at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
 at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
 at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
 at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
 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:220)
 at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68)
 at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
 at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
 at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
 at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
 at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)

Problem is deep repeat of same instance of ActionQueue in AbstractSaveEventListener (line 318) and final modification of ActionQueue by inner transaction.

Upvotes: 0

Views: 574

Answers (1)

Naros
Naros

Reputation: 21133

In the documentation, there is a section called Conditional Auditing that discusses this.

The basic notion is you will need to override the Hibernate event listeners that Envers registers to handle triggering the auditing with your own custom implementations.

Your implementation will basically need to extend the Envers listeners and:

  1. Check that the event is for the entity-type you're interested in skipping.
  2. Check the modified state to see if only the condition that implies skipping occurred.
  3. If you want to skip, simply don't delegate to the super implementation.

If you are using the ValidityAuditStrategy instead of the DefaultAuditStrategy, I would highly recommend you avoid using conditional auditing for INSERT operations.

Using conditional auditing on UPDATE operations from what I can tell will work, but doing so on the original inserts will cause the ADD row never to be added and thus the ValidityAuditStrategy will assert on the first UPDATE you attempt to audit for that entity row.

The goal in Hibernate 6 is to move beyond the need for users to manipulate the event listeners for conditional auditing and move toward a more JPA event listener annotation like approach. For more details, see HHH-11326.

Upvotes: 1

Related Questions