首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JPA EventListener方法不调用对多到多集合的更改?

JPA EventListener方法不调用对多到多集合的更改?
EN

Stack Overflow用户
提问于 2013-06-12 10:31:58
回答 2查看 4K关注 0票数 8

我在Spring中使用带有Hibernate的JPA作为实现。

我使用EntityListener进行审计(Spring)和其他通知目的。一般来说,它工作得很好。但是,当对多到多集合/关系进行更改时,而不对实体本身的任何字段进行任何更改--,则不会触发EventListener@PostUpdate事件。

给出一个具体的例子:我有一个User和一个Role实体,它们之间有一个多到多的关系,使用一个底层表。如果我转到我的用户管理GUI,并向用户添加(或删除)角色,而不更改任何其他内容,"postUpdate“事件就不会被触发,审计信息不会被修改。

它有一些逻辑(在较低的级别上),因为用户或角色表都没有更新,只有关系表是。但是,关系本身并不是作为实体类建模的,因此不可能对其应用审计,至少在JPA级别上是不可能的,因此为实体本身触发更改事件是有意义的。

这是一种正常的JPA行为,还是特定于Hibernate?有什么解决办法吗?你会怎么做才能触发这个事件?思想?

注意:我发现很少提到这个限制,甚至更少的解决方案:这个问题 (没有有用的答案)和这篇文章发表在Hibernate的论坛上也没有任何答案。

EN

回答 2

Stack Overflow用户

发布于 2013-06-12 19:06:17

JPA规范非常不清楚对集合的更改,触发了对拥有它们的实体的前后更新回调。说到不清楚,我是说完全沉默。实际上,IMO规范中的措辞意味着不应该发生回调,因为在为该实体发送SQL update语句之前/之后应该进行预/后更新。

现在,如果拥有实体是版本化的,则Hibernate将其拥有的任何集合(任何属性)的更改视为强制在拥有实体上进行版本增量,这将触发实体的更新,从而触发更新后回调。

票数 6
EN

Stack Overflow用户

发布于 2022-09-21 06:04:28

你可以用特殊的钩子来捕捉这个动作。在我的例子中,我用EventIntegrator创建了一个EntityManagerFactory

代码语言:javascript
复制
@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”创建了一个实现。

代码语言:javascript
复制
@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中看到更多的钩子。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17063262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档