Search code examples
hibernatespring-dataspring-data-jpaspring-bootspring-data-rest

How to use Spring managed Hibernate interceptors in Spring Boot?


Is it possible to integrate Spring managed Hibernate interceptors (http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch14.html) in Spring Boot?

I'm using Spring Data JPA and Spring Data REST and need an Hibernate interceptor to act on an update of a particular field on an entity.

With standard JPA events it's not possible to get the old values, and hence I think I need to use the Hibernate interceptor.


Solution

  • There's not a particularly easy way to add a Hibernate interceptor that is also a Spring Bean but you can easily add an interceptor if it's managed entirely by Hibernate. To do that add the following to your application.properties:

    spring.jpa.properties.hibernate.ejb.interceptor=my.package.MyInterceptorClassName
    

    If you need the Interceptor to also be a bean you can create your own LocalContainerEntityManagerFactoryBean. The EntityManagerFactoryBuilder from Spring Boot 1.1.4 is a little too restrictive with the generic of the properties so you need cast to (Map), we'll look at fixing that for 1.2.

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder factory, DataSource dataSource,
            JpaProperties properties) {
        Map<String, Object> jpaProperties = new HashMap<String, Object>();
        jpaProperties.putAll(properties.getHibernateProperties(dataSource));
        jpaProperties.put("hibernate.ejb.interceptor", hibernateInterceptor());
        return factory.dataSource(dataSource).packages("sample.data.jpa")
                .properties((Map) jpaProperties).build();
    }
    
    @Bean
    public EmptyInterceptor hibernateInterceptor() {
        return new EmptyInterceptor() {
            @Override
            public boolean onLoad(Object entity, Serializable id, Object[] state,
                    String[] propertyNames, Type[] types) {
                System.out.println("Loaded " + id);
                return false;
            }
        };
    }