使用Spring Boot和Spring Data JPA的Hibernate拦截器或监听器

时间:2016-09-23 14:47:22

标签: spring hibernate spring-boot spring-data spring-data-jpa

我想在保存对象的子集合之前运行一些检查(cascade = all)。

我正在使用Spring Boot和Spring Data JPA,并且想知道哪种方法最好:Hibernate监听器或拦截器。每个的优点/缺点是什么?你碰巧有一个你认为最好的方法的例子吗?

在使用XML配置之前我使用过Hibernate监听器:

    <property name="eventListeners">
        <map>
            <entry key="post-update">
                <list>
                    <ref bean="myListener" />
                </list>
            </entry>
        </map>
    </property>

在会话工厂(旧项目)上。但是现在我的大部分配置都是注释(导致Spring Boot),我希望尽可能简单明了地保持配置,所以拦截器可能是更好的解决方案。

谢谢。

2 个答案:

答案 0 :(得分:17)

我为自己做了很多关于此的事情并且认为我会分享我的工作(我在底部包含了有用的(非内联)链接。)

拦截

要使用拦截器,可以扩展org.hibernate.EmptyInterceptor类并覆盖要拦截的方法。 你可能想要onSave(...)

package foo.bar;

import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import java.io.Serializable;

public class MyInterceptor extends EmptyInterceptor {
    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        // do your checks here
        return false;
    }
}

你必须使用Spring / Hibernate register your interceptor。 您可以在application.properties or application.yml

中执行此操作
spring:
  jpa:
    properties:
      hibernate.ejb.interceptor: foo.bar.MyInterceptor

拦截器的优势在于它(可能)代码更少,配置相对简单。 缺点是您的整个应用程序只能有一个,并且API可能会让您感到困惑。

事件监听器

对于事件,您实现了Hibernate的org.hibernate.event.spi.*Listener接口之一。 你可能想要org.hibernate.event.spi.PreInsertEventListener

您必须在EventListenerRegistry中注册您的活动。 要执行此操作,您可以将课程设为@Component@Autowire EntityManagerFactory到您的班级,并创建@PostConstruct方法来注册课程。

package foo.bar;

import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;

@Component
public class MyEventListener implements PreInsertEventListener {
    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @PostConstruct
    private void init() {
        SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(this);
    }

    @Override
    public boolean onPreInsert(PreInsertEvent preInsertEvent) {
        // do your checks here
        return false;
    }
}

听众的优势在于,您可以拥有任意数量的API,API比拦截器更好,代码和配置都集中在一个地方。 缺点是配置 更长,更复杂。

答案 1 :(得分:2)

你好

首先,您可以检查: https://www.baeldung.com/database-auditing-jpa ,其中详细说明了每个选项。

我个人会推荐易于使用和理解的休眠拦截器。在大多数情况下,取决于项目的复杂性。

要在您的应用程序中进行配置,您只需添加: spring.jpa.properties.hibernate.ejb.interceptor = path.to.interceptor (在application.properties中)。拦截器本身应为 @Component

只要拦截器实际上不使用任何bean 。否则会有点复杂,但是我很乐意提供解决方案。

别忘了添加application-test.properties和 EmptyInterceptor ,以在测试中不使用日志记录系统(或您要用于此系统的任何东西)有帮助)。

希望这对您有用。

最后一点:总是更新您的Spring / Hibernate版本(尽可能使用最新版本),随着新版本尝试尽可能减少配置,您将看到大多数代码将变得多余。可能。