Home > Blockchain >  Make DB changes with hibernate listener
Make DB changes with hibernate listener

Time:10-22

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