Как предотвратить возникновение исключения InvalidDataAccessApiUsage, когда транзакция активна - PullRequest
0 голосов
/ 18 апреля 2019

Я обновлял наши проекты до Hibernate 5.4.2. Наконец, при использовании Spring 4.3.18.В большинстве случаев все прошло успешно, за исключением исключения, которое я получаю в одном из наших интеграционных тестов.Исключение возникает, когда выполняется операция удаления.Удаление - это один из нескольких объектов, которые повторяются в списке.Первые 8 успешно, но 9-го я получаю следующее исключение:

org.springframework.dao.InvalidDataAccessApiUsageException: выполнение запроса на обновление / удаление;вложенное исключение - javax.persistence.TransactionRequiredException: выполнение запроса на обновление / удаление

Я прошел по коду и вижу, что я нахожусь в активной транзакции, по крайней мере Spring сообщает об этом,но EntityManager сообщает, что он не присоединен к транзакции.

Active Trasnaction is debugger

Мой 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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...