【问题标题】:JTA EntityManager cannot use getTransaction() [Spring + Hibernate + EntityManager]JTA EntityManager 不能使用 getTransaction() [Spring + Hibernate + EntityManager]
【发布时间】:2012-05-24 22:30:44
【问题描述】:

我正在使用 Spring + JPA + Hibernate + EntityManager 与数据库通信。我收到 'A JTA EntityManager cannot use getTransaction()' 错误。请提供您的见解并帮助我解决问题。

beans.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)

以下是我的道课:-

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

非常感谢您的帮助。

【问题讨论】:

    标签: spring hibernate jpa entitymanager


    【解决方案1】:

    首先我想告诉你我有同样的问题。对此进行研究后,我发现此页面包含您的帖子以及“gkamal”的答案。

    我认为答案是说,如果您尝试在应用程序中使用 "global" JTA 事务并且它不起作用,那么不要使用它,而是使用它“本地” JDBC 事务。

    但是如果你需要使用全局 JTA 事务那么你必须使用它。

    好吧,我将为您提供我在研究中找到的解决方案。

    有些属性依赖于应用程序服务器。我使用 glassfish,这个解决方案运行良好,但我认为您使用的是 JBOSS(由于您在 persistence.xml 的 jta-data-source 中使用的值)我将为 JBOSS AS 编写值,但在 JBOSS 中因为我没有证明它,我只是在 glassfish 中证明它。

    在您的 persistence.xml 中,您必须添加另一个属性:

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

    此属性的值取决于 AP 服务器。

    在您的 beans.xml 文件中,您必须查看实体管理器工厂和事务管理器。此外,您已经在 web.xml 中指明了您在应用程序中引用了哪些持久性单元。

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

    这些属性的值取决于应用服务器(我使用 glassfish)。我认为您必须使用 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>
    

    希望解决方案对您有所帮助。它对我有用。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我不明白你要我做什么。你想让我发表我的评论作为答案吗?好吧,这不是答案,对吧?
      • 我已更新我的答案以解决您在评论中提出的问题 - 现在看看答案。持久性单元事务类型 =“RESOURCE_LOCAL”。这就是我之前评论的意思。
      猜你喜欢
      • 2012-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多