Hibernate4.3升级5.X报TransactionManagerDelegate强转异常如何排查
Hibernate 4.3升级5.X版本启动报TransactionManager类型转换异常排查
问题背景
尝试将当前基于Hibernate 4.3的项目升级至Hibernate 5.X版本,项目现有Maven依赖配置如下:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.2.0.Final</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.0.11.Final</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> <exclusion> <artifactId>jta</artifactId> <groupId>javax.transaction</groupId> </exclusion> <exclusion> <artifactId>jboss-transaction-api_1.2_spec</artifactId> <groupId>org.jboss.spec.javax.transaction</groupId> </exclusion> <exclusion> <artifactId>jboss-logging</artifactId> <groupId>org.jboss.logging</groupId> </exclusion> </exclusions> </dependency> <dependency> <artifactId>jboss-logging</artifactId> <groupId>org.jboss.logging</groupId> <version>3.2.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>5.0.11.Final</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency>
项目同时引入spring-orm 4.2.9用于数据库连接管理,已将datasource.xml配置文件中原本的Hibernate 4版本SessionFactory配置:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
替换为适配Hibernate 5的配置:
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
服务启动加载过程中抛出异常,错误栈如下:
2022-06-08 16:24:31,335 ERROR [STDERR] java.lang.ClassCastException: com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate cannot be cast to javax.transaction.TransactionManager 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform.locateTransactionManager(JBossAppServerJtaPlatform.java:42) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.retrieveTransactionManager(AbstractJtaPlatform.java:87) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.getTransactionManager(AbstractJtaPlatform.java:98) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.engine.transaction.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy.canRegisterSynchronization(TransactionManagerBasedSynchronizationStrategy.java:39) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.canRegisterSynchronization(AbstractJtaPlatform.java:131) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.pulse(JtaTransactionCoordinatorImpl.java:141) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.<init>(JtaTransactionCoordinatorImpl.java:92) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl.buildTransactionCoordinator(JtaTransactionCoordinatorBuilderImpl.java:28) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:274) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1332) 2022-06-08 16:24:31,336 ERROR [STDERR] at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:684) 2022-06-08 16:24:31,336 ERROR [STDERR] at com.al6.jtob.data.dao.GenericHibernateDAO.getSession(GenericHibernateDAO.java:75)
排查定位步骤
- 根因判定:该类型转换异常由JTA接口版本冲突导致。类路径下同时存在多份不同类加载器加载、或不同版本的
javax.transaction.TransactionManager接口,JBoss容器自带的Arjuna(JBossTS)事务管理器实现类,和Hibernate尝试转换时使用的接口不是同一个Class对象,因此触发ClassCastException。从异常栈可以看出,Hibernate 5自动探测到了JBoss容器环境,自动选用JBossAppServerJtaPlatform加载容器侧的TransactionManager,此时依赖不匹配就会触发报错。 - 第一步:排查JTA依赖冲突。执行命令
mvn dependency:tree输出全量依赖树,搜索所有javax.transaction、jboss-transaction-api相关的依赖,确认是否存在多版本JTA API共存的问题。如果项目部署在JBoss/WildFly容器中,将所有JTA相关API依赖的scope设置为provided,直接使用容器提供的标准JTA接口,避免项目打包时将不同版本的JTA接口带入WEB-INF/lib目录,和容器自带接口冲突。 - 第二步:修正Hibernate JTA平台配置。如果项目实际使用本地JDBC事务、不依赖容器JTA事务,直接在Hibernate配置中显式指定关闭JTA平台自动探测,避免Hibernate误识别容器环境,配置项如下:
<prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform</prop>
如果确实需要使用JBoss容器的JTA事务,移除hibernate-core依赖中对jboss-transaction-api_1.2_spec的排除配置,保证Hibernate侧引用的JTA接口版本和Arjuna事务管理器实现的接口版本完全一致。
- 第三步:修复关联依赖兼容性问题。当前使用的
hibernate-validator 4.2.0.Final是适配Hibernate 4的老旧版本,存在传递引入旧版本JTA、日志依赖的风险,升级到和Hibernate 5.0.11匹配的5.2.x系列版本即可。 - 第四步:清理缓存后验证。删除项目target目录、容器的temp/deploy缓存目录后重新打包部署,确认类路径下无重复JTA接口类,再验证会话创建、事务操作是否正常。
内容的提问来源于stack exchange,提问作者user2178964
相关产品推荐
相关产品推荐

