Tomcat下Spring5+Hibernate5+Atomikos4整合:JTA事务定位失败问题
I’ve been down this road before with Spring + Hibernate + Atomikos on Tomcat— that org.hibernate.HibernateException: Unable to locate current JTA transaction error is no fun. Let’s walk through what’s off in your setup and get it fixed.
First, let’s break down the key issues I spot in your config and code:
- Your
LocalSessionFactoryBeanhas conflicting properties that are throwing Hibernate off when trying to find the JTA transaction - The static fields in your
SpringJtaPlatformAdaptercan cause lifecycle issues with Spring’s bean initialization - There’s a missing piece in linking Spring’s transaction management to Hibernate’s JTA context
Let’s fix each part step by step:
Step 1: Clean Up the SessionFactory Configuration
Your current LocalSessionFactoryBean has properties that should be handled by Atomikos, not Hibernate directly. Let’s trim those out and set the correct JTA properties:
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"/> <property name="hibernateProperties"> <props> <!-- Keep your cache settings as-is --> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> <prop key="net.sf.ehcache.configurationResourceName">/ehcache/ehcache.xml</prop> <!-- Critical JTA settings - these tell Hibernate to use Spring/Atomikos transactions --> <prop key="hibernate.transaction.jta.platform">cgaweb.common.atomikos.SpringJtaPlatformAdapter</prop> <prop key="hibernate.current_session_context_class">jta</prop> <prop key="javax.persistence.transactionType">JTA</prop> <!-- Database and other core settings --> <prop key="hibernate.max_fetch_depth">2</prop> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.id.new_generator_mappings">true</prop> <prop key="hibernate.mapping.precedence">class, hbm</prop> </props> </property> <!-- Remove the hibernate.connection.datasource property here - Atomikos manages this via JNDI --> </bean>
What changed:
- Removed
hibernate.connection.datasource,hibernate.connection.autocommit,hibernate.connection.release_mode, andconnection.driver_class— these are all managed by Atomikos for JTA, so Hibernate doesn’t need to handle them - Fixed
javax.persistence.transactionTypeto be uppercaseJTA(some implementations are case-sensitive here)
Step 2: Fix the SpringJtaPlatformAdapter
Using static fields in this adapter is risky because Hibernate might try to access them before Spring has finished initializing the bean. Let’s switch to instance fields and use Spring’s autowiring properly:
public class SpringJtaPlatformAdapter extends AbstractJtaPlatform { private TransactionManager transactionManager; private UserTransaction userTransaction; @Override protected TransactionManager locateTransactionManager() { return transactionManager; } @Override protected UserTransaction locateUserTransaction() { return userTransaction; } @Autowired public void setJtaTransactionManager(JtaTransactionManager jtaTransactionManager) { this.transactionManager = jtaTransactionManager.getTransactionManager(); this.userTransaction = jtaTransactionManager.getUserTransaction(); } }
Key fixes:
- Got rid of static fields— now each bean instance holds its own references, which plays nice with Spring’s lifecycle
- Added
@Autowiredto the setter so Spring automatically injects theJtaTransactionManagerwhen initializing the adapter - Removed redundant setters since we’re pulling everything from the
JtaTransactionManager
Step 3: Enable Transaction Management in Spring
You need to tell Spring to handle transaction annotations. If you’re using XML config, add this to your application-context.xml (don’t forget the tx namespace in the header):
First, add the namespace to the root bean element:
xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
Then add the annotation-driven transaction management:
<tx:annotation-driven transaction-manager="transactionManager"/>
If you’re using Java config instead, just add @EnableTransactionManagement to your configuration class.
This ensures that when you annotate your service methods with @Transactional, Spring starts a JTA transaction that Hibernate can pick up.
Step 4: Verify Tomcat JNDI Datasource Setup
Since you’re using java:/comp/env/jdbc/myoracle, make sure your Tomcat context.xml has the Atomikos-managed XA datasource configured correctly. Here’s an example:
<Resource name="jdbc/myoracle" auth="Container" type="com.atomikos.jdbc.AtomikosDataSourceBean" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" uniqueResourceName="myoracle" xaDataSourceClassName="oracle.jdbc.xa.client.OracleXADataSource" xaProperties.URL="jdbc:oracle:thin:@//your-db-host:1521/your-sid" xaProperties.user="your-db-user" xaProperties.password="your-db-password" maxPoolSize="20" minPoolSize="5"/>
This ensures the datasource is properly registered with Atomikos for JTA transaction management.
Quick Final Checks
- Double-check your dependencies: you’ll need
transactions-hibernate5-4.0.4.jar(not justtransactions-jta-4.0.4.jar) to get Atomikos working with Hibernate 5 - Make sure your service methods are annotated with
@Transactional— without this, Spring won’t start a transaction for Hibernate to find - Ensure your
hibernate.cfg.xmldoesn’t override any of the JTA settings we configured in Spring
After making these changes, Hibernate should correctly locate the active JTA transaction managed by Spring and Atomikos, and that error should disappear.
内容的提问来源于stack exchange,提问作者Loic Kouam

