没有可用于当前线程的实际事务的EntityManager – 无法可靠地处理“刷新”调用

一些背景信息:我正在尝试将一个大项目从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:

  org.springframework spring-context 4.3.5.RELEASE   org.springframework spring-context-support 4.3.5.RELEASE   org.springframework spring-core 4.3.5.RELEASE   org.springframework spring-jdbc 4.3.5.RELEASE   org.springframework spring-orm 4.3.5.RELEASE   org.springframework spring-tx 4.3.5.RELEASE   org.springframework spring-web 4.3.5.RELEASE   org.springframework spring-webmvc 4.3.5.RELEASE   org.springframework spring-test 4.3.5.RELEASE test  

对于Hibernate:

  org.hibernate.common hibernate-commons-annotations 5.0.1.Final   org.hibernate hibernate-core 5.2.6.Final   org.hibernate hibernate-entitymanager 5.2.6.Final   org.hibernate.javax.persistence hibernate-jpa-2.1-api 1.0.0.Final   org.hibernate hibernate-jpamodelgen 5.2.6.Final provided  

persistence.xml(完整):(这里有些东西已被更改,但没有帮助:添加了jta-data-source,xsd版本已更新)

   org.hibernate.jpa.HibernatePersistenceProvider myproject-ds_jndi META-INF/named-queries.xml org.myproj.core.domain.Message   

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

   ...      classpath:configuration.properties classpath:externalized-queries.properties                     ${transactionManagerLookupClass} org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform       ... 

打开事务的类中的相关片段演示了此处使用的注释:

 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方法时会发生exception):

 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没有正确连接到Hibernates实体管理器,这就是exception的原因,因为trasanction本身似乎已经创建,但每当它试图保持这个exception过时。 毕竟我觉得它不再适用它很奇怪,虽然它与这些框架的旧版本一起运行良好。 旧版本的配置是否有任何重大变化?

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

扫描似乎有效。 如果查看堆栈跟踪,您可以看到EntityManager Proxy (com.sun.proxy。$ Proxy163), SharedEntityManagerCreator预期转发到SharedEntityManagerCreator

但是,在创建SharedEntityManager之前,它会检查是否存在事务,并且此检查失败。 该事务应由@Transactional注释创建。 这通过Spring AOP发生,创建扩展DBLockingImpl的GCLIB代理或实现Locking的JDK代理。 这可以通过在方法内设置断点并查看callstack以查看方法的调用方式来确定。

看看DBLockingImpl我注意到你使用的是SpringBeanAutowiringInterceptor ,它表明DBLockingImpl不是一个Spring bean,但你只需要将Spring bean自动装入它。 如果是这种情况,那么我认为这是你的问题,因为DBLockingImpl不会被代理AOP,因此不会应用@Transactional。

尝试使DBLockingImpl成为一个spring bean。