Spring Framework 6结合Tomcat/Payara使用JTA的方法及异常咨询
问题1:在Payara/Tomcat上结合纯Spring Framework使用JTA
Payara 实现方案
Payara作为Java EE兼容服务器,自带JTA事务管理器,纯Spring可直接集成:
- 引入Spring事务依赖:确保项目包含
spring-tx,版本与你的Spring核心版本匹配。 - 开启事务管理:在Spring配置类添加
@EnableTransactionManagement注解。 - 配置JTA事务管理器:
通过JNDI获取Payara内置的UserTransaction和TransactionManager,并注入到Spring的JtaTransactionManager中:@Bean public JtaTransactionManager transactionManager() throws NamingException { JtaTransactionManager tm = new JtaTransactionManager(); tm.setUserTransaction(new JndiTemplate().lookup("java:comp/UserTransaction")); tm.setTransactionManager(new JndiTemplate().lookup("java:comp/TransactionManager")); return tm; } - 业务层使用事务:在需要事务的方法上添加
@Transactional注解,可指定传播行为、隔离级别等属性。
Tomcat 实现方案
Tomcat无内置JTA支持,需结合第三方事务管理器(如Atomikos):
- 引入依赖:添加Atomikos的
transactions-jta、transactions-hibernate(若用Hibernate),以及Spring的spring-tx。 - 配置Atomikos事务管理器:
@Bean public UserTransaction userTransaction() throws SystemException { UserTransactionImp userTransactionImp = new UserTransactionImp(); userTransactionImp.setTransactionTimeout(300); return userTransactionImp; } @Bean public TransactionManager transactionManager() { return new TransactionManagerImp(); } @Bean public JtaTransactionManager jtaTransactionManager(UserTransaction userTransaction, TransactionManager transactionManager) { JtaTransactionManager tm = new JtaTransactionManager(); tm.setUserTransaction(userTransaction); tm.setTransactionManager(transactionManager); return tm; } - 配置JTA兼容数据源:使用Atomikos的
AtomikosDataSourceBean包装实际数据源,确保数据源参与分布式事务:@Bean public AtomikosDataSourceBean dataSource() { AtomikosDataSourceBean ds = new AtomikosDataSourceBean(); ds.setUniqueResourceName("myDataSource"); ds.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource"); Properties props = new Properties(); props.setProperty("user", "dbUser"); props.setProperty("password", "dbPass"); props.setProperty("url", "jdbc:mysql://localhost:3306/mydb"); ds.setXaProperties(props); return ds; } - 开启事务管理并使用:同样添加
@EnableTransactionManagement,业务方法加@Transactional。
问题2:Payara+Hibernate获取EntityManager时出现
ClassCircularityError 该错误通常由类加载冲突或Hibernate版本与Payara内置版本不兼容导致,解决方案如下:
- 版本对齐:Payara自带Hibernate实现,需确保项目引入的Hibernate版本与Payara内置版本一致。例如Payara 5.x对应Hibernate 5.x,避免引入Hibernate 6.x等不兼容版本。
- 排除冲突依赖:在Maven/Gradle中排除项目中与Payara内置重复的Hibernate模块,比如
hibernate-core、hibernate-jpa-api,让Payara使用自带版本:
Maven示例:<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.32.Final</version> <scope>provided</scope> <!-- 标记为服务器提供 --> </dependency> - 关闭Hibernate类增强:在
persistence.xml中添加配置,关闭Hibernate的字节码增强,避免与Payara的增强机制冲突:<property name="hibernate.ejb.use_class_enhancer" value="false"/> - 清理服务器缓存:删除Payara域目录下的
generated和cache文件夹(路径通常为domains/domain1/generated、domains/domain1/cache),重启服务器清除旧类文件。 - 检查部署包:确保WAR包中不包含Payara已提供的Java EE API或实现类(如
javax.persistence-api),避免类加载器重复加载。
内容的提问来源于stack exchange,提问作者Pereq
相关产品推荐
相关产品推荐

