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

ccc*_*ccc 5 spring hibernate spring-data spring-data-jpa spring-boot

我想在保存一个对象的子集合之前运行一些检查(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>
Run Code Online (Sandbox Code Playgroud)

在会议工厂(旧项目).但是现在我的大多数配置都在注释中(导致Spring Boot)并且我希望尽可能保持简单和轻便,因此拦截器可能是更好的解决方案.

谢谢.

Dil*_*ing 24

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

拦截器

要使用拦截器,可以扩展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;
    }
}
Run Code Online (Sandbox Code Playgroud)

你必须使用Spring/Hibernate 注册你的拦截器.您可以在application.properties或application.yml中执行此操作.

spring:
  jpa:
    properties:
      hibernate.ejb.interceptor: foo.bar.MyInterceptor
Run Code Online (Sandbox Code Playgroud)

拦截器的优点是(可能)更少的代码和相对简单的配置.缺点是您只能为整个应用程序使用一个,并且API可能会令人困惑.

事件监听器

对于事件,您实现了Hibernate的一个org.hibernate.event.spi.*Listener接口.你可能想要org.hibernate.event.spi.PreInsertEventListener在你的情况下.

你必须在中注册你的活动EventListenerRegistry.要做到这一点,你可以让你的类@Component,@AutowireEntityManagerFactory到类,并创建一个@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

听众的好处是你可以拥有任意数量的API,API比拦截器更好,代码和配置都集中在一个地方.不足之处是配置更长,更复杂.


  • 太棒了,我看起来像你一样得到了很好的指导。 (2认同)

Rar*_*raș 5

你好

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

我个人推荐Hibernate Interceptor,易于使用和理解。根据项目的复杂程度,大多数情况下就可以了。

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

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

不要忘记在 application-test.properties 中添加一个EmptyInterceptor ,以便在测试中不使用日志系统(或任何您想要使用它的东西)(这不会很有帮助)。

希望这对您有用。

最后一点:始终更新您的 Spring / Hibernate 版本(尽可能使用最新版本),您会发现大多数代码将变得多余,因为新版本会尝试尽可能减少配置。