我使用Spring + JPA + Hibernate + EntityManager与数据库通信。我得到'JTA EntityManager无法使用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)
Folowing是我的道教课: -
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;
}
}
非常感谢您的帮助。
答案 0 :(得分: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>
答案 1 :(得分: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中指明了你在应用程序中引用的持久性单元。
<强>的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>
我希望解决方案对您有所帮助。它对我有用。