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
}
});
...
}