Recently I was working on a Spring Boot application and I wanted to put together Spring and Hibernate with JPA EntityListeners.
As you may know, any JPA EntityListener class is not in the scope of Spring or any Ioc, as long as you bring them together. If you have the requirement to do this, there are a lot of examples in blogs, describing workarounds like
http://esus.com/hibernate-4-integrator-pattern-springs-di/ or https://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners which in the end are doing autowiring programmatically (i.e. by using org.springframework.web.context.support.SpringBeanAutowiringSupport).
In the recent versions of Spring and Hibernate, this work became obsolete (as I described also on https://stackoverflow.com/questions/47941717/spring-dependency-injection-into-jpa-entity-listener/55452014#55452014).
Since Hibernate 5.3 there is a so called org.hibernate.resource.beans.container.spi.BeanContainer, which makes Hibernate aware of Spring or CDI beans. Later, org.springframework.orm.hibernate5.SpringBeanContainer was added with Spring 5.1, so you do not need to handle autowiring any more. See details of this feature in https://github.com/spring-projects/spring-framework/issues/20852
As an example of a JPA EntityListener, you can add the @Component annotation and wire any Spring bean to it.
@Component
public class MyEntityListener{
private MySpringBean bean;
@Autowired
public MyEntityListener(MySpringBean bean){
this.bean = bean;
}
@PrePersist
public void prePersist(final Object entity) {
…
}
}
To make Hibernate aware of this component bean, there are two scenarios:
1) You are using Spring Boot: Then you do not have to do anything, because the configuration of LocalContainerEntityManagerFactoryBean is done automatically in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration.
2) Outside of Spring Boot, you have to register SpringBeanContainer to Hibernate like this:
@Configuration
….
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory beanFactory) {
LocalContainerEntityManagerFactoryBean emfb = …
emfb.getJpaPropertyMap().put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
…
return emfb;
}