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.

1 thought on “Spring-Managed Hibernate Event Listeners”

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

Leave a Reply

Your email address will not be published. Required fields are marked *