AssertionFailure occurs detach after persist

        var emf = Persistence.createEntityManagerFactory("test");
        var em = emf.createEntityManager();
        var tx = em.getTransaction();

        try {
            tx.begin();

            var member1 = new Member("1", "bob", 23);

            em.persist(member1);
            em.detach(member1);

            var member2 = new Member("2", "chirs", 42);
            em.persist(member2);

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
        emf.close();

Hi

In the provided code, It encounter an issue when trying to commit the transaction, which results in an AssertionFailure Exception. The expected behavior was for member1 to be ignored, and member2 to be inserted into the database.

The stacktrace is following.

ERROR: HHH000099: an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: possible non-threadsafe access to session
javax.persistence.RollbackException: Error while committing the transaction
	at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:81)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
	at test.Main.main(Main.java:19)
Caused by: org.hibernate.AssertionFailure: possible non-threadsafe access to session
	at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:111)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
	at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407)
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489)
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3303)
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2438)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
ERROR: HHH000099: an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: possible non-threadsafe access to session

The code functions correctly when an additional persist request (in this case, member2) is not present and the persistence context has no managing entities. However, the exception is thrown when an additional persist request is made during the transaction, causing the commit to fail.

The exception is being thrown from the EntityInsertAction class. When the detach method is called, it removes entity from first-level cache(PersistenceContext). However, it doesn’t remove the associated action from the actionQueue. As a result, when an action containing a detached entity is executed, it triggers an exception.

EntityInsertAction:109

			final EntityEntry entry = persistenceContext.getEntry( instance );
			if ( entry == null ) {
				throw new AssertionFailure( "possible non-threadsafe access to session" );
			}

Is this behavior intentional, or is it advisable not to use it in this manner?

I don’t know why you’re detaching an entity right after you pass it to persist as that will not make the entity persistent. You have to flush first.
Either way, I’d say this is a bug. The detach operation should remove entity actions involving the entity.

1 Like

It was just a curiosity. I know the JPA specification states that you ‘must use the flush method before the detach method,’ but I was wondering what would happen in Hibernate.

Thank you for the reply.