Я обновлял наши проекты до Hibernate 5.4.2. Наконец, при использовании Spring 4.3.18.В большинстве случаев все прошло успешно, за исключением исключения, которое я получаю в одном из наших интеграционных тестов.Исключение возникает, когда выполняется операция удаления.Удаление - это один из нескольких объектов, которые повторяются в списке.Первые 8 успешно, но 9-го я получаю следующее исключение:
org.springframework.dao.InvalidDataAccessApiUsageException: выполнение запроса на обновление / удаление;вложенное исключение - javax.persistence.TransactionRequiredException: выполнение запроса на обновление / удаление
Я прошел по коду и вижу, что я нахожусь в активной транзакции, по крайней мере Spring сообщает об этом,но EntityManager сообщает, что он не присоединен к транзакции.
Мой EntityManager подключен к Spring следующим образом:
<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>
Файл persistence.xml выглядит следующим образом:
<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>
Нет ошибок при запуске приложения, но есть некоторые сообщения INFO и DEBUG из 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'
Я просто не могу определить причину того, почему EntityManager показывает, что нет транзакции, пока есть одна активная в Spring.Я предполагаю, что есть конфигурация, которая может отсутствовать, но я не могу определить, что.
Любая помощь очень ценится.Спасибо…
После дальнейшего исследования кажется, что это вызвано методом LogicalConnectionManagedImpl # afterCompletion (), который, в свою очередь, вызывает реализацию суперкласса resetConnection () в методе AbstractLogicalConnectionImplementor # resetConnection ().
protected void afterCompletion() {
resetConnection( initiallyAutoCommit );
initiallyAutoCommit = false;
afterTransaction();
}
В resetConnection () состояние соединения устанавливается на 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);
}
}
Это заставляет EntityManager сообщать, что он не присоединен к транзакции, даже еслиесть активная транзакция, которой управляет Spring.Это приводит к сбою любого оператора обновления, сделанного на этом этапе, потому что Hibernate считает, что нет активной транзакции.
Существует флаг, который я могу предоставить в моих файлах persistence.xml:
hibernate.allow_update_outside_transaction = true
Но это кажется мне довольно опасным, поскольку спецификация JPA запрещает такое поведение по уважительным причинам.
Это изменение в методе resetConnection () в Hibernate явно является причиной проблемы, ноЯ не могу определить, почему это вызывается в данный момент.Spring по-прежнему считает, что есть активная сделка.В то время как моя работа SQL выполняется в синхронизации afterCommit, действительно не должно быть проблем, поскольку транзакция все еще активна.
Есть ли способ обойти эту проблему, кроме использования свойства в persistence.xml?