我想在保存对象的子集合之前运行一些检查(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),我希望尽可能简单明了地保持配置,所以拦截器可能是更好的解决方案。
谢谢。
答案 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版本(尽可能使用最新版本),随着新版本尝试尽可能减少配置,您将看到大多数代码将变得多余。可能。