When I was using Hibernate 4 in a previous Spring application, the following was sufficient to register all interception of DB Insert/Update/Delete events. There was a simple Configuration class and the actual Interceptor implementation.
Config class
@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);
}
}
Interceptor class
@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) {
//...
}
But when I ported this code to a Spring Boot 2.1.2 app using Hibernate 5, I started getting the following startup error about SessionFactory not being found:
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.
I googled around and I only found some more elaborate and messy code that I don't trust or understand, https://stackoverflow.com/a/48471227/1005607
This is way too complicated now and I just need a simple way to wire this interceptor. What's the right way to put in the interceptors and get past this SessionFactory error?
I found the solution on Bozho's blog, the code can stay mostly the same as before, but I can't autowire SessionFactory
anymore: I have to autowire EntityManagerFactory
instead, and then "unwrap" it as SessinFactoryImpl sf = emf.unwrap(..)
. That's the only change.
Latest code: Configuration:
@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);
}
}