Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register Event Listener with Spring and Hibernate 5

Now, I would like to upgrade my application from Spring hibernate 3 to 5

Under hibernate 3, I create a POST-COMMIT-INSERT|UPDATE|DELETE event listener like below

<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="annotatedClasses">
        <list>
            ....
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            ....
        </props>
    </property>
    <property name="eventListeners">
        <map>
            <entry key="post-commit-insert">
                <bean class="xxxx.AuditLogPostInsertEventListener" />
            </entry>
            <entry key="post-commit-update">
                <bean class="xxxx.AuditLogPostUpdateEventListener" />
            </entry>
            <entry key="post-commit-delete">
                <bean class="xxxx.AuditLogPostDeleteEventListener" />
            </entry>
        </map>
    </property>
</bean>

Now, I try to create the event listener under Hibernate 5 but not success

<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="annotatedClasses">
        <list>
            ...
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            ...
        </props>
    </property>
    <property name="eventListeners">
        <map>
            <entry key="post-commit-insert">
                <bean class="xxxx.AuditLogPostInsertEventListener" />
            </entry>
            <entry key="post-commit-update">
                <bean class="xxxx.AuditLogPostUpdateEventListener" />
            </entry>
            <entry key="post-commit-delete">
                <bean class="xxxx.AuditLogPostDeleteEventListener" />
            </entry>
        </map>
    </property>
</bean>

The follow message was shown

Invalid property 'eventListeners' of bean class [org.springframework.orm.hibernate5.LocalSessionFactoryBean]: Bean property 'eventListeners' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

I tried to follow this stackoverflow but still not success.

PreInsert and PreUpdate Event Listener in hibernate

I changed the config like below but still not success

<bean id="auditInterceptor" class="xxxx.EntityEventListenerRegistry" />

<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="annotatedClasses">
        <list>
            ...
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            ...
        </props>
    </property>
    <property name="entityInterceptor" ref="xxxx.EntityEventListenerRegistry" />
</bean>
like image 871
leonlai Avatar asked Aug 15 '18 07:08

leonlai


2 Answers

The most portable way of setting the Hibernate entity listeners is via the org.hibernate.integrator.spi.Integrator. This way, you can get it working for both JpaTransactionManager and HibernateTransactionManager.

Implementing the Integrator interface

You need to implement the Integrator as follows:

public class ReplicationEventListenerIntegrator 
        implements Integrator {
 
    public static final ReplicationEventListenerIntegrator INSTANCE = 
        new ReplicationEventListenerIntegrator();
 
    @Override
    public void integrate(
            Metadata metadata,
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {
 
        final EventListenerRegistry eventListenerRegistry =
                serviceRegistry.getService(EventListenerRegistry.class);
 
        eventListenerRegistry.appendListeners(
            EventType.POST_INSERT, 
            ReplicationInsertEventListener.INSTANCE
        );
         
        eventListenerRegistry.appendListeners(
            EventType.POST_UPDATE, 
            ReplicationUpdateEventListener.INSTANCE
        );
         
        eventListenerRegistry.appendListeners(
            EventType.PRE_DELETE, 
            ReplicationDeleteEventListener.INSTANCE
        );
    }
 
    @Override
    public void disintegrate(
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {
 
    }
}

Via the eventListenerRegistry, you can register the event listeners.

Setting the hibernate.integrator_provider configuration property

Once you are done, you need to set up the hibernate.integrator_provider configuration property.

  1. If you're using a persistence.xml configuration file, then you can set the property like this:

     <property name="hibernate.integrator_provider"
               value="com.vladmihalcea.book.hpjp.hibernate.listener.ReplicationEventListenerIntegrator"
     />
    
  2. Or, if you use Spring Boot, you can configure this property via application.properties like this:

     spring.jpa.properties.hibernate.integrator_provider=com.vladmihalcea.book.hpjp.hibernate.listener.ReplicationEventListenerIntegrator
    
like image 71
Vlad Mihalcea Avatar answered Sep 19 '22 00:09

Vlad Mihalcea


Per my comment, the interceptor needs to implement org.hibernate.Interceptor.

like image 37
bungrudi Avatar answered Sep 20 '22 00:09

bungrudi