InvalidDataAccessApiUsage Exception being raised while Transaction is active

I’ve been upgrading our projects to Hibernate 5.4.2.Final while using Spring 4.3.18. Most everything has been successful except for an exception I am receiving in one of our integration tests. An Exception is being raised when a delete operation is being performed. The delete is one of several objects that are being iterated over in a list. The first 8 are successful but on the 9th I am receiving the following exception:

org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query

I’ve stepped through the code and I can see that I am in an active transaction, at least Spring is reporting so, but the EntityManager is reporting that it is not joined to a transaction.

My EntityManager is wired in Spring as follows:

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" primary="true">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="databasePlatform" value="org.hibernate.dialect.MySQL55Dialect" />
            </bean>
        </property>
        <property name="jpaPropertyMap">
            <props>
                <prop key="hibernate.transaction.factory_class">org.springframework.orm.hibernate5.HibernateTransactionManager</prop>
            </props>
        </property>
    </bean>

The persistence.xml file is as follows:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL55Dialect"/>
            <property name="hibernate.dialect.storage_engine=" value="innodb" />
            <property name="hibernate.hbm2ddl.auto" value=""/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <!-- Implicit Naming Strategy ensures that table & column names are genereated as expected -->
            <property name="hibernate.implicit_naming_strategy" value="common.hibernate.model.naming.ImplicitNamingStrategy"/>
        </properties>
    </persistence-unit>
</persistence>

There are no errors during application startup but there are some INFO and DEBUG messages from Hibernate:

2019-04-18 10:23:07,770 [main sessionId: vaultId: userId: origReqUri:] INFO  org.hibernate.validator.internal.util.Version  - HV000001: Hibernate Validator 6.0.14.Final
2019-04-18 10:23:09,559 [main sessionId: vaultId: userId: origReqUri:] DEBUG org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator  - No JtaPlatform was specified, checking resolver
2019-04-18 10:23:09,560 [main sessionId: vaultId: userId: origReqUri:] DEBUG org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator  - No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.           StandardJtaPlatformResolver]
2019-04-18 10:23:09,581 [main sessionId: vaultId: userId: origReqUri:] DEBUG org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver  - Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2019-04-18 10:23:09,581 [main sessionId: vaultId: userId: origReqUri:] INFO  org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator  - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2019-04-18 10:23:09,803 [main sessionId: vaultId: userId: origReqUri:] INFO  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean  - Initialized JPA EntityManagerFactory for persistence unit 'default'

I simply cannot identify a reason as to why the EntityManager is showing that there is no transaction while there is one active in Spring.

Any help is greatly appreciated.
Thank you…

After further investigation it seems that this is being caused by the LogicalConnectionManagedImpl#afterCompletion() method, which in turn calls its super class implementation of resetConnection() in AbstractLogicalConnectionImplementor#resetConnection() method.

	protected void afterCompletion() {
		resetConnection( initiallyAutoCommit );
		initiallyAutoCommit = false;

		afterTransaction();
	}

In resetConnection(), the connection status is set to NOT_ACTIVE:

	protected void resetConnection(boolean initiallyAutoCommit) {
		try {
			if ( initiallyAutoCommit ) {
				log.trace( "re-enabling auto-commit on JDBC Connection after completion of JDBC-based transaction" );
				getConnectionForTransactionManagement().setAutoCommit( true );
				status = TransactionStatus.NOT_ACTIVE;
			}
		}
		catch ( Exception e ) {
			log.debug(
					"Could not re-enable auto-commit on JDBC Connection after completion of JDBC-based transaction : " + e
			);
		}
	}

This is causing the EntityManager to report that it is not joined to a transaction, even though there is an active transaction that Spring is managing. This causes any update statement made at this point to fail because Hibernate thinks that there is not an active transaction.

There is a flag which I can supply in my persistence.xml files:

<property name="hibernate.allow_update_outside_transaction" value="true"/>

But this seems rather dangerous to me as the JPA spec disallows this behavior for good reasons.

This change in Hibernate’s resetConnection() method is clearly the cause of the problem but I can’t determine why this is being invoked at this point. Spring still believes that there is an active transaction. While my SQL work is being performed in an afterCommit synchronization there really should be no issue as the transaction is still active.

Is there any way around this issue other than using the property in persistence.xml?