在Spring和Hibernate 5中注册事件监听器

时间:2018-08-15 07:58:32

标签: java spring hibernate events listener

现在,我想将我的应用程序从Spring hibernate 3升级到5

在休眠3下,我创建了一个POST-COMMIT-INSERT | UPDATE | DELETE事件侦听器,如下所示

<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>

现在,我尝试在Hibernate 5下创建事件监听器,但不成功

<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>

显示了以下消息

  

Bean类[org.springframework.orm.hibernate5.LocalSessionFactoryBean]的无效属性'eventListeners':   Bean属性“ eventListeners”不可写或具有无效的setter方法。   setter的参数类型是否与getter的返回类型匹配?

我尝试遵循此stackoverflow,但仍未成功。

PreInsert and PreUpdate Event Listener in hibernate

我更改了如下配置,但仍然没有成功

<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>

4 个答案:

答案 0 :(得分:1)

根据我的评论,拦截器需要实现 org.hibernate.Interceptor

答案 1 :(得分:1)

您也可以像我一样使用java类注册休眠EventListener。

请检查此一项。它可以帮助您。

1)向Integrator注册EventListener。

    @Override
   public void integrate(Metadata metadata, SessionFactoryImplementor 
         sessionFactory, SessionFactoryServiceRegistry serviceRegistry) 
   {

      EventListenerRegistry eventListenerRegistry = 
            serviceRegistry.getService(EventListenerRegistry.class);

     /* eventListenerRegistry.getEventListenerGroup(EventType.SAVE)
                     .appendListener(new SaveUpdateEventListenerImp());*/

      eventListenerRegistry.getEventListenerGroup(EventType.SAVE_UPDATE)
      .appendListener(new SaveUpdateEventListenerImp());

      eventListenerRegistry.getEventListenerGroup(EventType.LOAD)
                     .appendListener(new LoadEventListenerImp());

      eventListenerRegistry.getEventListenerGroup(EventType.REFRESH)
                     .appendListener(new RefreshEventListenerImp());
   }

2)我们可以从这里检查LoadEventListener。只需实现LoadEventListener。      当您从数据库加载Book实体时,LoadEventListener将调用。

  public class LoadEventListenerImp implements LoadEventListener {

   private static final long serialVersionUID = 1L;
   private static Logger logger = LogManager.getLogger(LoadEventListenerImp.class);

   @Override
   public void onLoad(LoadEvent e, LoadType type) throws HibernateException {
      logger.info("onLoad is called.");
      Object obj = e.getResult();
      if (obj instanceof Book) {
         Book book = (Book) obj;
         logger.info("Book on load event {} " , book);
      }
   }

答案 2 :(得分:1)

正如我在this article中所解释的那样,设置Hibernate实体侦听器的最可移植的方法是通过org.hibernate.integrator.spi.Integrator。这样,您可以使其同时适用于JpaTransactionManagerHibernateTransactionManager

实现Integrator界面

您需要如下实现Integrator

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) {

    }
}

通过eventListenerRegistry,您可以注册事件监听器。

设置hibernate.integrator_provider配置属性

完成后,您需要设置hibernate.integrator_provider配置属性。

  1. 如果您使用的是 persistence.xml 配置文件,则可以这样设置属性:

    <property name="hibernate.integrator_provider"
              value="com.vladmihalcea.book.hpjp.hibernate.listener.ReplicationEventListenerIntegrator"
    />
    
  2. 或者,如果您使用Spring Boot,则可以通过 application.properties 来配置此属性,如下所示:

    spring.jpa.properties.hibernate.integrator_provider=com.vladmihalcea.book.hpjp.hibernate.listener.ReplicationEventListenerIntegrator
    

答案 3 :(得分:0)

最后,我尝试了这一点并且工作正常。

@Component

公共类EntityEventListenerRegistry {

@Autowired
private SessionFactory sessionFactory;

@Autowired
private AuditLogPostInsertEventListener auditLogPostInsertEventListener;

@Autowired
private AuditLogPostUpdateEventListener auditLogPostUpdateEventListener;

@Autowired
private AuditLogPostDeleteEventListener auditLogPostDeleteEventListener;

@PostConstruct
public void registerListeners() {
    EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class);
    registry.getEventListenerGroup(EventType.POST_COMMIT_INSERT).appendListener(auditLogPostInsertEventListener);
    registry.getEventListenerGroup(EventType.POST_COMMIT_UPDATE).appendListener(auditLogPostUpdateEventListener);
    registry.getEventListenerGroup(EventType.POST_COMMIT_DELETE).appendListener(auditLogPostDeleteEventListener);
}

}