jpa 当前线程没有可用的具有实际事务的EntityManager-无法可靠地处理“flush”调用

bjg7j2ky  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(352)

一些背景信息:我正在尝试将一个大项目从Hibernate 3.6.8迁移到5.2.5(包括JPA 2.0到2.1的升级),Spring 3.2.3到4.3.5,并且面临着严重的问题。到目前为止,Spring和Hibernate的配置还没有改变,并且在旧版本上工作得很好,但是随着升级问题的出现,我自己无法解决。
我得到的例外是:

2017-01-16 10:15:25,635 ERROR [[ACTIVE] ExecuteThread: '15' for queue: 'weblogic.kernel.Default (self-tuning)'] org.myproject.common.messaging.BaseMDB: Code: (11702) Source: (Common) Exception caught - Exception org.springframework.dao.InvalidDataAccessApiUsageException in org.myproject.core.processing.message.MessageReceiverImpl caught
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call
                at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:413)
                at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)
                at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491)
                at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
                at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
                at com.sun.proxy.$Proxy187.flushAndClear(Unknown Source)
                at org.myproject.core.BasePersistenceMDB.synchronizeBackend(BasePersistenceMDB.java:46)
                at org.myproject.core.BasePersistenceMDB.onTextMessage(BasePersistenceMDB.java:32)
                at org.myproject.common.messaging.BaseMDB.evaluateJMSMessage(BaseMDB.java:100)
                at org.myproject.common.messaging.BaseMDB.onMessage(BaseMDB.java:51)
                at sun.reflect.GeneratedMethodAccessor591.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
                at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
                at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
                at com.oracle.pitchfork.intercept.MethodInvocationInvocationContext.proceed(MethodInvocationInvocationContext.java:100)
                at com.oracle.pitchfork.intercept.JeeInterceptorInterceptor.invoke(JeeInterceptorInterceptor.java:117)
                at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
                at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
                at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
                at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
                at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(Unknown Source)
                at com.sun.proxy.$Proxy121.onMessage(Unknown Source)
                at weblogic.ejb.container.internal.MDListener.execute(MDListener.java:451)
                at weblogic.ejb.container.internal.MDListener.transactionalOnMessage(MDListener.java:375)
                at weblogic.ejb.container.internal.TokenBasedJMSMessagePoller.processOneMessage(TokenBasedJMSMessagePoller.java:279)
                at weblogic.ejb.container.internal.TokenBasedJMSMessagePoller.run(TokenBasedJMSMessagePoller.java:121)
                at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:548)
                at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
                at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call
                at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:282)
                at com.sun.proxy.$Proxy163.flush(Unknown Source)
                at org.myproject.core.data.dao.impl.MyPersistenceContextImpl.flushAndClear(MyPersistenceContextImpl.java:49)
                at sun.reflect.GeneratedMethodAccessor616.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
                ... 28 more

**我的配置如下所示:pom.xml(相关片段):**适用于Spring:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.5.RELEASE</version>
  </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.5.RELEASE</version>
    <scope>test</scope>
  </dependency>

对于休眠:

<dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.0.1.Final</version>
      </dependency>
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
       <version>5.2.6.Final</version>
      </dependency>
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.6.Final</version>
      </dependency>
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
      </dependency>
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-jpamodelgen</artifactId>
        <version>5.2.6.Final</version>
        <scope>provided</scope>
      </dependency>

persistence.xml(完整):(此处有些内容已更改,但没有帮助:添加了jta-data-source,更新了xsd版本)

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">

    <persistence-unit name="MYPROJECT_PU" transaction-type="JTA">        
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>myproject-ds_jndi</jta-data-source>

        <mapping-file>META-INF/named-queries.xml</mapping-file>

        <class>org.myproj.core.domain.Message</class>

    </persistence-unit>

</persistence>

appContext.xml(相关代码片段):(升级后在jpaProperties中添加了一个额外的属性)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/jdbc
    http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

...

<bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean
        class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

    <bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:configuration.properties</value>
                <value>classpath:externalized-queries.properties</value>
            </list>
        </property>
    </bean>

    <bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="${datasourceJndiName}"></property>
    </bean>

    <!-- Indicates a JpaVendorAdapter implementation for Hibernate EntityManager. -->
    <bean id="jpaVendorAdapter"
        class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="database" value="${databaseVendor}" />
        <property name="showSql" value="${showSql}" />
        <property name="generateDdl" value="${generateDdl}" />
        <property name="databasePlatform" value="${databaseDialect}" />
    </bean>

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="${persistenceXmlFileLocation}" />
        <property name="persistenceUnitName" value="${persistenceUnitName}" />
        <property name="dataSource" ref="jndiDataSource" />
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.transaction.manager_lookup_class">${transactionManagerLookupClass}</prop>
                <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform</prop> <!-- this was newly added -->

            </props>
        </property>
    </bean>

    <tx:annotation-driven />

    <tx:jta-transaction-manager />

...

来自打开事务的类的相关代码段,演示此处使用了哪些注解:

import java.sql.SQLException;
import java.util.Set;

import javax.interceptor.Interceptors;

import org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

...

@Interceptors(SpringBeanAutowiringInterceptor.class)
@Transactional(propagation = Propagation.REQUIRED)
public class DBLockingImpl implements Locking {

@Autowired
private DataSource dataSource;

这是呼叫entityManager的类别(此时已开启交易,但在此处的EntityManager上呼叫flush方法时会发生例外状况):

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository(value = "persistenceContext")
public class PersistenceContextImpl
    implements PersistenceContext {

    /**
     * Instance variable for EntityManager.
     */
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void flushAndClear() {
        entityManager.flush();
        entityManager.clear();
    }
}

所以,有人能帮我解决这个问题吗?我不明白缺少了什么,为什么我会遇到这个异常。我得到的印象是Spring没有正确连接到Hibernate实体管理器,这就是为什么会出现异常,因为事务本身似乎是创建的,但是每当它试图保持这个异常时,它就会飞起来。毕竟,我觉得它不再工作很奇怪,虽然它在这些框架的旧版本中工作得很好。2旧版本的配置有什么大的变化吗?

rseugnpd

rseugnpd1#

我怀疑这可能是您的组件扫描或软件包扫描的问题。我在您的Spring配置文件中找不到软件包扫描代码。请检查或更新您的配置文件。

e4eetjau

e4eetjau2#

如果您查看堆栈跟踪,可以看到EntityManager Proxy(com.sun.proxy.$Proxy163),并且它按预期转发到SharedEntityManagerCreator
但是,在创建SharedEntityManager之前,它会检查是否有事务,但是这个检查失败了。创建扩展DBLockingImpl的GCLIB代理或实现Locking的JDK代理。这可以通过在方法内设置断点并查看调用堆栈来确定方法是如何调用的。
看一下DBLockingImpl,我注意到你使用了SpringBeanAutowiringInterceptor,这表明DBLockingImpl不是一个Spring bean,但是你只是将Spring bean自动连接到它。如果是这种情况,那么我认为这是你的问题,因为DBLockingImpl将不会被AOP代理,因此不会应用@Transactional。
试着让DBLockingImpl成为 Spring Bean 。

相关问题