我在Spring中使用带有Hibernate的JPA作为实现。
我使用EntityListener进行审计(Spring)和其他通知目的。一般来说,它工作得很好。但是,当对多到多集合/关系进行更改时,而不对实体本身的任何字段进行任何更改--,则不会触发EventListener的@PostUpdate事件。
给出一个具体的例子:我有一个User和一个Role实体,它们之间有一个多到多的关系,使用一个底层表。如果我转到我的用户管理GUI,并向用户添加(或删除)角色,而不更改任何其他内容,"postUpdate“事件就不会被触发,审计信息不会被修改。
它有一些逻辑(在较低的级别上),因为用户或角色表都没有更新,只有关系表是。但是,关系本身并不是作为实体类建模的,因此不可能对其应用审计,至少在JPA级别上是不可能的,因此为实体本身触发更改事件是有意义的。
这是一种正常的JPA行为,还是特定于Hibernate?有什么解决办法吗?你会怎么做才能触发这个事件?思想?
注意:我发现很少提到这个限制,甚至更少的解决方案:这个问题 (没有有用的答案)和这篇文章发表在Hibernate的论坛上也没有任何答案。
发布于 2013-06-12 19:06:17
JPA规范非常不清楚对集合的更改,触发了对拥有它们的实体的前后更新回调。说到不清楚,我是说完全沉默。实际上,IMO规范中的措辞意味着不应该发生回调,因为在为该实体发送SQL update语句之前/之后应该进行预/后更新。
现在,如果拥有实体是版本化的,则Hibernate将其拥有的任何集合(任何属性)的更改视为强制在拥有实体上进行版本增量,这将触发实体的更新,从而触发更新后回调。
发布于 2022-09-21 06:04:28
你可以用特殊的钩子来捕捉这个动作。在我的例子中,我用EventIntegrator创建了一个EntityManagerFactory。
@Service
@RequiredArgsConstructor
public class EventIntegrator {
private final EntityManagerFactory entityManagerFactory;
private final CustomPostCollectionUpdateEventListener postCollectionUpdateEventListener;
@PostConstruct
private void init() {
SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.POST_COLLECTION_UPDATE)
.appendListener(postCollectionUpdateEventListener);
}之后,我为“implementation”创建了一个实现。
@Component
@RequiredArgsConstructor
public class CustomPostCollectionUpdateEventListener implements PostCollectionUpdateEventListener {
@Override
public void onPostUpdateCollection(PostCollectionUpdateEvent event) {
if (event.getAffectedOwnerOrNull() != null) {
var object = (AEntity<?>) event.getAffectedOwnerOrNull();
Arrays.stream(object.getClass().getMethods())
.filter(method -> method.isAnnotationPresent(PrePersist.class) && method.getParameterCount() == 0)
.forEach(method -> {
try {
method.invoke(object);
} catch (IllegalAccessException | InvocationTargetException e) {
ExceptionUtils.throwUnsupportedOperationException("@PrePersis method was found, but cannot be called");
}
});
object.log(Event.UPDATE);
}
}
}我还为PostUpdateEventListener创建了一个实现,因为有时我在没有CollectionUpdateEvent的情况下捕获PostUpdateEvent!
您可以在org.hibernate.event.spi.EventType中看到更多的钩子。
https://stackoverflow.com/questions/17063262
复制相似问题