【问题标题】:ConcurrentModificationException while updating data within Hibernate event listener在 Hibernate 事件侦听器中更新数据时出现 ConcurrentModificationException
【发布时间】:2022-10-24 10:28:32
【问题描述】:

我在 DB 表上有一个 Hibernate 侦听器。当这个监听器被触发时,我想查询另一个表并更新一些数据。但是,当我尝试这样做时,会收到如下错误:

    org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction 
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:571)
    ...
    Caused by: java.util.ConcurrentModificationException
        at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)

我的代码看起来像:

    @Slf4j
    @RequiredArgsConstructor
    @Component
    public class MyTableHibernateListener implements PostInsertEventListener, PreUpdateEventListener, PostUpdateEventListener {
        private final JPQLQueryFactory queryFactory;

        @Override
        public boolean onPreUpdate(PreUpdateEvent event) {
            try {
                ...

                // Some working logic to set some data within the current MyTable.

                // Try to query another table below
                AnotherTable row = queryFactory.select(QAnotherTable.anotherTable)
                    .from(QAnotherTable.anotherTable)
                    .where(...)
                    .fetchOne();
                ...
                log.info("Success");
                return false;
            } catch (Exception e) {
                log.error("Failure", e);
                throw e;
            }
        }
    }

记录了“成功”并且没有记录失败,因此看起来错误发生在侦听器方法之外。我还没有在另一个表中进行任何数据库更改,所以看起来甚至不允许查询另一个表。有人可以帮助我了解这里可能存在什么问题以及推荐的解决方法可能是什么?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    您需要将查询包装在 BeforeTransactionCompletionProcess 中(我假设您希望更新在同一事务中运行)并将其注册到 Hibernate 操作队列中。

        @Override
        public boolean onPreUpdate(PreUpdateEvent event) {
            event.getSession().getActionQueue().registerProcess(new BeforeTransactionCompletionProcess() {
                @Override
                public void doBeforeTransactionCompletion(SessionImplementor session) {
                    //your query
                }
            });
            ...
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多