Home > Net >  ConcurrentModificationException while updating data within Hibernate event listener
ConcurrentModificationException while updating data within Hibernate event listener

Time:10-24

I have a Hibernate listener on DB table. When this listener gets triggered, I want to query another table and update some data. However, when I try to do so, I get an error like:

    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)

My code looks something like:

    @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;
            }
        }
    }

"Success" is logged and no failure is logged, so it looks like the error occurs outside the listener method. I'm also not yet making any DB changes in the other table, so it looks like even querying another table isn't allowed. Can someone help me understand what might be the issue here and what the recommended workaround may be?

CodePudding user response:

You need to wrap your query in a BeforeTransactionCompletionProcess (I assume you want the update to run in same transaction) and register it into Hibernate action queue.

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