Spring IllegalStateException: A JTA EntityManager cannot use getTransaction()

匿名 (未验证) 提交于 2019-12-03 02:31:01

问题:

So after a big refactoring project, I am left with this exception and am unsure as how to correct it. It's dealing with some code that I did not write and I am unfamiliar with how it all works. There are other questions out there dealing with this exception, but none seem to fit my situation.

The class which uses EntityManager is SpecialClaimsCaseRepositoryImpl:

package com.redacted.sch.repository.jpa;  //Imports  @Repository public class SpecialClaimsCaseRepositoryImpl extends SimpleJpaRepository<SpecialClaimsCaseDto, SpecialClaimsCaseDto.Id> implements SpecialClaimsCaseRepository{      @PersistenceContext(unitName = "schManager")     private EntityManager em;            //Some autogenerated methods      public void setEntityManager(EntityManager em) {         this.em = em;     }      public EntityManager getEntityManager() {         return em;     } } 

Persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"     version="1.0">      <persistence-unit name="schManager">         <provider>org.hibernate.ejb.HibernatePersistence</provider>         <jta-data-source>jdbc/SCH_DS</jta-data-source>         <class>com.redacted.sch.domain.model.SpecialClaimsCaseDto</class>         <properties>             <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />             <property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory" />             <property name="hibernate.cache.use_query_cache" value="true" />             <property name="hibernate.cache.use_second_level_cache" value="true" />             <property name="hibernate.dialect" value="com.bcbsks.hibernate.dialect.DB2Dialect" />             <property name="hibernate.format_sql" value="true" />             <property name="hibernate.generate_statistics" value="false" />             <property name="hibernate.jdbc.use_scrollable_resultset" value="true" />         </properties>     </persistence-unit> </persistence> 

sch_model_spring.xml:

<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"     xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">          <context:component-scan base-package="com.redacted.repository.jpa,               com.redacted.sch.domain.model,               com.redacted.sch.repository.jpa,               com.redacted.sch.service,               com.redacted.sch.service.impl"/>          <tx:annotation-driven />          <tx:jta-transaction-manager />          <!-- Data source used for testing -->         <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">             <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />             <property name="url" value="jdbc:db2:redacted.redacted.com" />             <property name="username" value="redacted" />             <property name="password" value="redacted" />         </bean>          <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">               <property name="persistenceUnitName" value="schManager" />               <property name="dataSource" ref="dataSource" />         </bean>          <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">             <property name="entityManagerFactory" ref="entityManagerFactory" />         </bean>  </beans> 

And here's my project structure:

>

Here's a portion of the stack trace, with the full trace at this fpaste

Caused by: java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()     at org.hibernate.ejb.AbstractEntityManagerImpl.getTransaction(AbstractEntityManagerImpl.java:985)     at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:67)     at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380)     ... 80 more 

I'm a total noob here, so if any other information is needed just ask and I'll update.

Thanks for all the help!

回答1:

The problem is your configuration. You have hibernate configured for JTA.

<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" /> 

Whereas you are using local transactions instead of distributed transactions.

at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) 

You have 2 possible solutions

  1. remove the JpaTransactionManager and replace it with a JTA transaction manager
  2. remove the remove the hibernate.transaction.manager_lookup_class from the hibernate settings.

If you don't really need distributed transactions option 2 is the easiest, if you need distributed transactions simply adding <tx:jta-transaction-manager /> will setup a proper JTA tx manager for your environment. Remove the definition for the JpaTransactionManager.

Update:

Your configuration is flawed in 2 ways.

  1. Your EntityManager configuration already contains a jndi lookup for the datasource, which you override in your applicationContext by configuring a local datasource
  2. You have both a <tx:jta-transaction-manager /> and JpaTransactionManager which one do you want to use? At the moment the latter is overriding the first one.

Create 2 seperate configurations one for local testing and one for production using JTA en JNDI lookups. (Preferable your testing code only overrides the beans necessary).



回答2:

Use WebSphereTransactionManagerLookup for the transaction manager lookup in Hibernate

<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereTransactionManagerLookup" /> 

and remove your current transaction manager and replace it with the WebSphereUowTransactionManager.

<tx:annotation-driven/> <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/> 

for your transaction manager lookup in Spring.

See IBM Websphere and Spring docs for more in depth documentation.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!