2017-01-17 22 views
3

背景情報:大きなプロジェクトをHibernate 3.6.8から5.2.5に移行しようとしています(JPAアップグレード2.0から2.1を含む)。 3.2.3から4.3.5の春にかけて、深刻な問題に直面しています。これまでSpringとHibernateの設定は変更されておらず、古いバージョンではうまくいきましたが、自分では解決できないアップグレードの問題が発生しました。現在のスレッドで実際のトランザクションが利用できるEntityManagerがない - 'flush'コールを確実に処理できない

私は取得しています例外は次のとおりです。

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(関連スニペット):春のため

<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> 

for Hibe rnate:

<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データ・ソースが追加されている、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に1つの余分プロパティを追加しました)

<?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の(トランザクションがすでにこの時点で開かれているが、例外を呼び出すクラスでありますflushメソッドは、ここでのEntityManagerに呼び出されたときに)起こる:

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エンティティマネージャに正しく接続していないという印象を受けます。なぜなら、その例外は、それ自体が作成されているように見えますが、この例外を保持しようとするたびに発生します。結局のところ、このフレームワークの古いバージョンではうまくいきましたが、それはもう機能していないというのは変です。古いバージョンの設定に大きな変更がありましたか?

+0

私は '' 'PersistenceContextImpl'''クラスに困惑していますが、なぜPersistenceContextアノテーションをオーバーライドしますか? Springでは、注入されたEntityManagerはTransactionalおよびThreadLocalストレージと対話するプロキシであり、Transactionalアノテーションが尊重されていないのとほとんど同じです。他の誰かがこれを前に試して、その原因を知っていれば、あなたは非常に幸運になると思います。私はあなたがこれを理解するためにデバッグする必要があることを恐れています。 –

+0

プロジェクトを既にアップグレードしている場合、Mavenと膨大なXML設定を取り除いてGradleに切り替えることはできません;) –

+0

@KlausGroenbaekここで混乱して申し訳ありませんが、PersistenceContextImplはこのケースではPersistenceContextアノテーションですが、使用され、データベースとのやりとりがある通常のクラスです。 Gradleについての情報をありがとうございます;)私は将来Gradleをチェックしますが、MavenからGradleへの移行はかなり致命的であると確信しています:D – ProgEngineer

答えて

0

これは、コンポーネントスキャンまたはパッケージスキャンで問題が発生する可能性があります。私はあなたの春の設定ファイルでパッケージのスキャンコードを見つけることができません。設定ファイルを確認または更新してください。

0

スキャンが機能するようです。スタックトレースを見ると、EntityManager Proxy(com.sun.proxy。$ Proxy163)が表示され、期待通りにSharedEntityManagerCreatorに転送されます。

ただし、SharedEntityManagerを作成する前に、トランザクションがあるかどうかをチェックし、このチェックは失敗します。トランザクションは@Transactional注釈で作成する必要があります。これは、Spring AOPを通じて、DBLockingImplを拡張するGCLIBプロキシを作成するか、Lockingを実装するJDKプロキシを作成することによって行われます。これは、メソッド内にブレークポイントを設定し、コールスタックを調べてメソッドがどのように呼び出されたかを確認することで判断できます。

投稿者SpringBeanAutowiringInterceptor私は、DBLockingImplがSpring Beanではなく、Spring Beanをその中に自動で入れていることがわかりました。この場合、DBLockingImplはAOPがプロキシされないため、@Transactionalは適用されないため、問題はあなたの問題だと思います。

DBLockingImplを春豆としてみてください。

関連する問題