Spring-Managed Hibernate Event Listeners
Hibernate offers event listeners as part of its SPI. You can hook your listeners to a number of events, including pre-insert, post-insert, pre-delete, flush, etc.
But sometimes in these listeners you want to use spring dependencies. I’ve written previously on how to do that, but hibernate has been upgraded and now there’s a better way (and the old way isn’t working in the latest versions because of missing classes).
This time it’s simpler. You just need a bean that looks like this:
@Component
public class HibernateListenerConfigurer {
@PersistenceUnit
private EntityManagerFactory emf;
@Inject
private YourEventListener listener;
@PostConstruct
protected void init() {
SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.POST_INSERT).appendListener(listener);
registry.getEventListenerGroup(EventType.POST_UPDATE).appendListener(listener);
registry.getEventListenerGroup(EventType.POST_DELETE).appendListener(listener);
}
}
It is similar to this stackoverflow answer, which however won’t work because it also relies on deprecated calsses.
You can also inject a List<..>
of listeners (though they don’t share a common interface, you can define your own).
As pointed out in the SO answer, you can’t store new entities in the listener, though, so it’s no use injecting a DAO, for example. But it may come handy to process information that does not rely on the current session.
Hibernate offers event listeners as part of its SPI. You can hook your listeners to a number of events, including pre-insert, post-insert, pre-delete, flush, etc.
But sometimes in these listeners you want to use spring dependencies. I’ve written previously on how to do that, but hibernate has been upgraded and now there’s a better way (and the old way isn’t working in the latest versions because of missing classes).
This time it’s simpler. You just need a bean that looks like this:
@Component public class HibernateListenerConfigurer { @PersistenceUnit private EntityManagerFactory emf; @Inject private YourEventListener listener; @PostConstruct protected void init() { SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class); EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class); registry.getEventListenerGroup(EventType.POST_INSERT).appendListener(listener); registry.getEventListenerGroup(EventType.POST_UPDATE).appendListener(listener); registry.getEventListenerGroup(EventType.POST_DELETE).appendListener(listener); } }
It is similar to this stackoverflow answer, which however won’t work because it also relies on deprecated calsses.
You can also inject a List<..>
of listeners (though they don’t share a common interface, you can define your own).
As pointed out in the SO answer, you can’t store new entities in the listener, though, so it’s no use injecting a DAO, for example. But it may come handy to process information that does not rely on the current session.
Thank for this!
Another approach is to use the traditional @EntityListeners on the Entity.
In the listener you can call the getBean method of this utility class :
@Component
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static T getBean(Class beanClass) {
if(context != null){
return context.getBean(beanClass);
}
return null;
}
}
It allows you not to test each time the instance type of the persisted object.