Search code examples
hibernatehibernate-envers

Implementing Conditional Envers Auditing (Hibernate 4.3.7.Final)


I want to audit ALL properties in my entity but only if some properties has changed. Following the steps described in the documentation (here), I`ve create my own implementation of EnversIntegrator :

public class EnversIntegrator extends org.hibernate.envers.event.spi.EnversIntegrator {
private static final Logger log = LoggerFactory.getLogger(EnversIntegrator.class);  
private AuditConfiguration enversConfiguration;
@Override
public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
    log.debug(".... integrate");
    final EventListenerRegistry listenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
    listenerRegistry.addDuplicationStrategy(EnversListenerDuplicationStrategy.INSTANCE);
    enversConfiguration = AuditConfiguration.getFor(configuration, serviceRegistry.getService(ClassLoaderService.class));
    if (enversConfiguration.getEntCfg().hasAuditedEntities()) {
        log.debug(".... Register listeners");
        listenerRegistry.prependListeners(EventType.POST_DELETE, new MyPostDeleteEventListener(enversConfiguration));
        listenerRegistry.prependListeners(EventType.POST_INSERT, new MyPostInsertEnversEventListener(enversConfiguration));
        listenerRegistry.prependListeners(EventType.POST_UPDATE, new  MyPostUpdateEnversEventListener(enversConfiguration));
    }
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
    if (enversConfiguration != null) {
        enversConfiguration.destroy();
    }
}

Where :

MyPostInsertEnversEventListener extends org.hibernate.envers.event.spi.EnversPostInsertEventListenerImpl

and

 MyPostUpdateEnversEventListener extends org.hibernate.envers.event.spi.EnversPostUpdateEventListenerImpl

Overriding onPostUpdate or onPostInsert(PostInsertEvent evt) has no effect, every time when I execute my test, a new record is added in _AUD table.

public void onPostUpdate(PostUpdateEvent evt) {     
    LOG.debug(" ... onPostUpdate " + evt.getEntity().getClass());
//here is my logic who decide if the super.onPostUpdate(evt) must be call or not  
//But NO  super.onPostUpdate(evt); is called !!!!!

}

Updating Address entity booth onPostUpdate and onPostInsert is called:

[DEBUG] xxxx.hibernate.MyPostUpdateEnversEventListener -  ... onPostUpdate class xxxxxxx.model.Address
[DEBUG] xxxx.hibernate.MyPostInsertEnversEventListener -  ... onPostInsert class org.hibernate.envers.DefaultRevisionEntity
[DEBUG] xxxx.hibernate.MyPostInsertEnversEventListener -  ... onPostInsert class java.util.HashMap

How can I prevent this new record creation in the _aud table?

Many thanks!


Solution

  • Debugging the code I`ve realize that "integrate" method in org.hibernate.envers.event.spi.EnversIntegrator is called too. In fact i've misplaced "hibernate.listeners.envers.autoRegister" parameter in spring configuration. This is my working configuration :

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="myTestDataSource" />
        <property name="packagesToScan" value="xyz.**.model" />
    
        <property name="jpaVendorAdapter" ref="jpaAdapter" />
        <property name="jpaProperties">
            <props>             
                          <prop key="hibernate.hbm2ddl.auto">validate</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.listeners.envers.autoRegister">false</prop>
            </props>
        </property>
        <property name="persistenceXmlLocation"
            value="classpath:spring/app-persistence.xml" />
    </bean>
    

    Thx Adam four your great work.