首页 > 解决方案 > Spring Boot 2.1.2、Hibernate 5:注册 Hibernate 事件监听器(插入/更新/删除)

问题描述

当我在之前的 Spring 应用程序中使用 Hibernate 4 时,以下内容足以注册所有对 DB Insert/Update/Delete 事件的拦截。有一个简单的配置类和实际的拦截器实现。

配置类

@Component
public class HibernateEntityEventListenerConfig {

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    private HibernateEntityEventListener entityEventListener;

    @PostConstruct
    public void registerListeners() {
          final EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
                    .getServiceRegistry().getService(EventListenerRegistry.class);
            registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener((PreInsertEventListener) entityEventListener);
            registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener((PreUpdateEventListener) entityEventListener);
            registry.getEventListenerGroup(EventType.PRE_DELETE).appendListener((PreDeleteEventListener) entityEventListener);
    }

}

拦截器类

@Component
public class HibernateEntityEventListener implements PreInsertEventListener,
                                                     PreUpdateEventListener,    
                                                     PreDeleteEventListener {

@Override
public boolean onPreInsert(PreInsertEvent event) {
  //...
}

@Override
public boolean onPreUpdate(PreUpdateEvent event) {
  //...
}

@Override
public boolean onPreDelete(PreUpdateEvent event) {
  //...
}

但是当我将此代码移植到使用 Hibernate 5 的 Spring Boot 2.1.2 应用程序时,我开始收到以下有关找不到SessionFactory的启动错误:

Field sessionFactory in util.HibernateEntityEventListenerConfig required 
a bean of type 'org.hibernate.SessionFactory' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.hibernate.SessionFactory' in your configuration.

我四处搜索,只发现了一些我不信任或不理解的更复杂和混乱的代码, https://stackoverflow.com/a/48471227/1005607

现在这太复杂了,我只需要一种简单的方法来连接这个拦截器。放置拦截器并克服这个 SessionFactory 错误的正确方法是什么?

标签: springhibernatespring-bootjpalistener

解决方案


我在Bozho 的博客上找到了解决方案,代码可以保持与以前大致相同,但我不能再自动接线SessionFactory了:我必须改为自动接线EntityManagerFactory,然后将其“解包”为SessinFactoryImpl sf = emf.unwrap(..). 这是唯一的变化。

最新代码: 配置:

@Component   
public class HibernateEntityEventListenerConfig {



@PersistenceUnit
private EntityManagerFactory emf;  // NOTE Can't autowire SessionFactory.

@Autowired
private HibernateEntityEventListener entityEventListener;

@PostConstruct
public void registerListeners() {
    // NOTE the emf.unwrap() to get the SessionFactoryImpl
    SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
    EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
                .getServiceRegistry().getService(EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener((PreInsertEventListener) entityEventListener);
        registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener((PreUpdateEventListener) entityEventListener);
        registry.getEventListenerGroup(EventType.PRE_DELETE).appendListener((PreDeleteEventListener) entityEventListener);
}

}

推荐阅读