You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 05:35:07