2

Spring + JPA + Hibernate + EntityManager を使用してデータベースと通信しています。「JTA EntityManager は getTransaction() を使用できません」というエラーが表示されます。あなたの洞察を提供し、私が問題を解決するのを手伝ってください.

ビーンズ.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans default-autowire="byName"
    ... xmlns definitions...
      xsi:schemaLocation="...">

    <context:component-scan base-package="com.mycompany.myproject" />

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

    <bean id="myDAO" class="com.mycompany.myproject.dao.myDAO" />

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven />
</beans>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence ... xmlns definitions xsi:schemaLocation="..." version="1.0">
    <persistence-unit name="TEST_DS">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/TEST_DS</jta-data-source>
        <class>com.twinspires.exchange.model.Test</class>
        <properties>
            <property name="hibernate.archive.autodetection" value="class, hbm" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="validate" /> <!-- create-drop update -->
            <property name="hibernate.cache.use_query_cache" value="true" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
              <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>             
        </properties>
    </persistence-unit>
</persistence>

例外スタックトレース (抜粋)

15:47:43,340 INFO  [STDOUT] DEBUG: org.springframework.transaction.annotation.AnnotationTransactionAttributeSource - Adding transactional method 'getName' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
15:47:43,343 INFO  [STDOUT] DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'transactionManager'
15:47:43,356 INFO  [STDOUT] DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [com.twinspires.exchange.dao.PicDAO.getName]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
15:47:44,114 INFO  [STDOUT] DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@c629e5] for JPA transaction
15:47:44,124 INFO  [STDOUT] DEBUG: org.springframework.orm.jpa.JpaTransactionManager - Could not rollback EntityManager after failed transaction begin
15:47:44,125 INFO  [STDOUT] java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
15:47:44,125 INFO  [STDOUT]     at org.hibernate.ejb.AbstractEntityManagerImpl.getTransaction(AbstractEntityManagerImpl.java:818)
15:47:44,126 INFO  [STDOUT]     at org.springframework.orm.jpa.JpaTransactionManager.closeEntityManagerAfterFailedBegin(JpaTransactionManager.java:412)
15:47:44,127 INFO  [STDOUT]     at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:381)
15:47:44,128 INFO  [STDOUT]     at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
15:47:44,129 INFO  [STDOUT]     at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
15:47:44,129 INFO  [STDOUT]     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
15:47:44,130 INFO  [STDOUT]     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
15:47:44,131 INFO  [STDOUT]     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
15:47:44,131 INFO  [STDOUT]     at $Proxy175.getName(Unknown Source)

以下は私のdaoクラスです:-

public class MyDao implements IMyDao {
      @PersistenceContext(unitName = "TEST_DS")
      private EntityManager entityManager;

      @Transactional
      public String getName() {            
            final Query query = entityManager.createQuery("from TestTable");
            final Object obj = query.getResultList().get(0);
            return obj == null ? "Empty" : (String) obj;
      }
}

あなたの助けに感謝します。

4

2 に答える 2

5

persitence.xmlからjta-datasourceを削除し、datasourceをBean j2ee:jdni-lookupとして構成して、LocalContainerEntityManagerFactoryBeanに挿入します。

これをpersistence.xmlから削除します

<jta-data-source>java:/TEST_DS</jta-data-source>

トランザクションタイプをリソースローカルに構成します

 <persistence-unit name="TEST_DS" transaction-type="RESOURCE_LOCAL">

Beans.xmlに変更します

<j2ee:jndi-lookup id="dataSource"  jndi-name="java:/TEST_DS"/>

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   <property name="dataSource" ref="dataSource"/>
</bean>
于 2012-05-17T11:28:45.213 に答える
3

まず、私は同じ問題を抱えていたことを伝えたいと思います。それについて調べていると、あなたの投稿と「gkamal」による回答でこのページを見つけました。

アプリケーションで「グローバル」 JTAトランザクションを使用しようとしていて、それが機能しない場合は、それを使用せず、代わりに「ローカル」 JDBCトランザクションを使用するという答えになると思います。

ただし、グローバル JTA トランザクションを使用する必要がある場合は、それを使用する必要があります。

さて、私の研究で見つけた解決策を紹介します。

アプリケーション サーバーに依存するプロパティがあります。私はglassfishを使用しており、このソリューションは正常に機能しますが、JBOSSを使用していると思います(persistence.xmlのjta-data-sourceで使用している値のため)JBOSS ASの値を書きますが、JBOSSで私はそれを証明していないので、グラスフィッシュでのみ証明しています。

persistence.xml には、別のプロパティを配置する必要があります。

<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>

このプロパティの値は AP サーバーによって異なります。

beans.xml ファイルで、エンティティ マネージャー ファクトリとトランザクション マネージャーを確認する必要があります。さらに、アプリケーションで参照している永続ユニットを web.xml で指定しました。

ビーンズ.xml

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="TEST_DS"/>
</bean>

トランザクション マネージャーでは、エンティティ マネージャー ファクトリを使用していますが、その必要はありません。このように、アプリケーション サーバーで使用されるトランザクション マネージャーとユーザー トランザクションを指定する必要があります。

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManagerName" value="java:appserver/TransactionManager"/>
        <property name="userTransactionName" value="java:comp/UserTransaction"/>
    </bean>

これらのプロパティの値はアプリ サーバーに依存します (私はグラスフィッシュを使用しています)。jboss ap の値を使用する必要があると思います。

 <property name="transactionManagerName" value="java:/TransactionManager"/>
        <property name="userTransactionName" value="UserTransaction"/>

しかし、私はそれを証明しませんでした。

最後に、glassfish では、beans.xml に次の Bean を配置する必要があります (理由はわかりません) (jboss ap では必要ないと思いますが、証明できるかもしれません)

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" > 
        <property name="persistenceUnits"> 
            <map> 
                <entry key="TEST_DS" value="persistence/TEST_DS"/> 
            </map> 
        </property> 
    </bean> 

web.xmlで、アプリケーションが使用する持続性ユニットを参照する必要があります。

<persistence-unit-ref>
    <persistence-unit-ref-name>persistence/TEST_DS</persistence-unit-ref-name>
    <persistence-unit-name>TEST_DS</persistence-unit-name>
</persistence-unit-ref>

解決策がお役に立てば幸いです。わたしにはできる。

于 2013-02-18T10:31:14.000 に答える