Resolving Concurrent Exceptions in Hibernate logger

In which I found and resolved a fix for an issue with the Hibernate debug logger causing entity relationship saves to fail with a ConcurrentModificationException.

Recently while working on a Hibernate ORM project, I ran into an interesting issue when an entity with relationships is saved inside a transaction.

  var myEntity = entityLoadByPK( "Person", theEntityID );

  myEntity.setAddress( otherEntity );;

// throws "ConcurrentModificationException" on transaction end.

Note this is not a complete test case - simply an example of when the issue occurs.

When the transaction completes, Lucee tries to flush the entity modifications, but this fails with the following error:

lucee.runtime.exp.NativeException: java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(
at java.base/java.util.HashMap$
at java.base/java.util.HashMap$
at org.hibernate.internal.util.EntityPrinter.toString(
at org.hibernate.event.internal.AbstractFlushingEventListener.logFlushResults(
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(
at org.hibernate.internal.SessionImpl.doFlush(
at org.hibernate.internal.SessionImpl.flush(
at org.lucee.extension.orm.hibernate.HibernateORMTransaction.end(
at lucee.runtime.orm.ORMConnection.setAutoCommit(
at lucee.runtime.orm.ORMDatasourceConnection.setAutoCommit(
at lucee.runtime.db.DatasourceManagerImpl.end(
at lucee.runtime.db.DatasourceManagerImpl.end(
at lucee.runtime.tag.Transaction.doFinally(

It turns out this issue is related to the Hibernate debug logger. In Lucee, Hibernate's log4j logger is set to a DEBUG level by default. That's fine, but it seems the logger actually mutates the logged entities during logging. Thus we get a concurrent modification exception.

To resolve this, all we have to do is de-escalate the logging level from DEBUG to WARN.

 * Resolves Hibernate ConcurrentModificationException when flushing an entity save with one-to-many relationships.
 * @see
var Logger = createObject( "java", "org.apache.log4j.Logger" );
var level = createObject( "java", "org.apache.log4j.Level" );
var log = Logger.getLogger( "org.hibernate" );
log.setLevel( level.WARN );

This should be done in the Application.cfc before ORM initializes - say, just below the this.ormSettings{} configuration block.

All thanks to @jclausen for this awesome find and easy fix!

August 20, 2021

« Cross-engine transaction detection in Hibernate v3+ - Redirecting Hibernate Logs to the CommandBox Console »