我希望在保存spring数据之前能够使用一些更复杂的保存逻辑。
我有这个JpaRepository:
public interface MyClassRepository extends JpaRepository<MyClass, Long> {
@Query("from com.package.MyClass as myClass where myClass.parent is null");
MyClass getRootMyClass();
...
}
和这个实体:
@Entity
@Table("MY_CLASS")
public class MyClass {
@ManyToOne
@JoinColumn("parent_id")
MyClass parent;
}
我希望能够检查父属性的null,并在存储库中设置root myClass。例如,像这样:
if(myClass.getParent() == null) {
myClass.setParent(getRootMyClass());
}
我无法使用实体中的@PrePersist
挂钩,因为它不知道存储库。我不能在存储库中这样做,因为它是一个接口 - 而不是一个类。放这个的最好的地方在哪里?
答案 0 :(得分:1)
如果您使用的是JDK8,可以将以下方法添加到MyClassRepository
:
public interface MyClassRepository extends JpaRepository<MyClass, Long> {
@Query("from com.package.MyClass as myClass where myClass.parent is null")
MyClass getRootMyClass();
default void checkSave(MyClass myClass) {
if (myClass.getParent() == null) {
myClass.setParent(getRootMyClass());
}
save(myClass);
}
}
然后,你应该调用checkSave()而不是save()
答案 1 :(得分:1)
你可以利用Hibernate的PreInsertEventListener
,你可以为Hibernate的每个prePersist
操作注册这样的拦截器;
@Component
public class MyEventListener implements PreInsertEventListener {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Autowired
private MyClassRepository myClassRepository;
@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) {
if (MyClass.class.equals(preInsertEvent.getEntity().getClass())) {
MyClass entity = (MyClass) preInsertEvent.getEntity();
if(myClass.getParent() == null) {
myClass.setParent(myClassRepository.getRootMyClass());
}
}
return false;
}
}
这种方法背后的想法是,Hibernate中的所有持久性事件都将被拦截,例如,如果存在一些级联插入,这仍然会触发。因此,此解决方案涵盖MyClass
的所有可能持久性,如果这对您的要求太多,则更好的其他更简单的解决方案。