Weblogic+Spring JTA事务环境下出现TransactionRequiredException求助
看起来你在Spring+Hibernate整合Weblogic JTA事务时碰到了执行数据库操作的问题,我之前也处理过类似的场景,结合你给出的错误日志:
return (<May 10, 2018 9:40:56 AM IST> <Warning> <org.apache.cxf.phase.PhaseInterceptorChain> <BEA-000000> <Application {http://stockquote.cxf.deployable.wls.com/}StockQuotePort... )
核心问题大概率是Weblogic JTA事务管理器与Hibernate的整合配置不当,同时可能伴随CXF Web服务与事务的绑定问题,下面给你梳理几个关键的排查和解决步骤:
1. 修正Hibernate的JTA平台配置
首先要确保Hibernate明确使用Weblogic的JTA平台,在hibernate.cfg.xml或者Spring的LocalSessionFactoryBean配置中,添加以下参数:
<!-- Hibernate核心JTA配置 --> <property name="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform</property> <property name="hibernate.transaction.coordinator_class">jta</property> <property name="hibernate.current_session_context_class">jta</property>
这些参数会让Hibernate自动适配Weblogic的JTA事务环境,避免Session和事务绑定失败。
2. 配置Spring事务管理器对接Weblogic JTA
Spring需要使用专门的WebLogicJtaTransactionManager来绑定Weblogic的全局事务,而不是默认的JTA实现。在Spring配置文件中添加:
<bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"> <!-- 指定Weblogic的UserTransaction JNDI名称,默认值即可 --> <property name="transactionManagerName" value="javax.transaction.UserTransaction"/> </bean>
如果使用注解式事务,若只有这一个事务管理器,@Transactional注解可省略transactionManager属性;若有多个,需明确指定该bean的id。
3. 检查Weblogic数据源的事务配置
登录Weblogic控制台,确认你的数据源已经开启JTA支持:
- 进入数据源配置页面,切换到「Transactions」标签页
- 勾选「Supports Global Transactions」,再根据数据库类型选择事务模式(单阶段提交或两阶段提交)
- 同时确认数据源的JNDI名称和Spring、Hibernate配置中引用的完全一致,例如
java:comp/env/jdbc/StockDB
4. 解决CXF Web服务与事务的绑定问题
错误日志中出现了CXF拦截器的警告,说明Web服务方法可能没有正确参与到JTA事务中。你可以在CXF端点配置中添加事务拦截器:
<jaxws:endpoint id="stockQuotePort" implementor="com.wls.deployable.cxf.stockquote.StockQuoteImpl" address="/StockQuotePort"> <jaxws:inInterceptors> <bean class="org.apache.cxf.transaction.TransactionalInInterceptor"/> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.transaction.TransactionalOutInterceptor"/> </jaxws:outInterceptors> </jaxws:endpoint>
同时在Web服务的实现方法上添加@Transactional注解,确保方法执行时触发事务上下文。
5. 规范Hibernate Session的获取方式
在DAO层,必须使用SessionFactory.getCurrentSession()来获取Session,而不是openSession()——因为JTA模式下,getCurrentSession()会自动绑定到当前的JTA事务,而openSession()会创建独立的Session,无法参与全局事务。示例代码:
@Repository public class StockDaoImpl implements StockDao { @Autowired private SessionFactory sessionFactory; @Override @Transactional public void saveStock(Stock stock) { sessionFactory.getCurrentSession().saveOrUpdate(stock); } }
6. 解决类依赖冲突问题
Weblogic 12c自带了部分Hibernate和JTA相关的类,可能和你应用打包的类版本冲突。你可以在weblogic.xml中配置优先使用应用的类:
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"> <container-descriptor> <prefer-application-packages> <package-name>org.hibernate.*</package-name> <package-name>org.springframework.transaction.*</package-name> <package-name>org.apache.cxf.*</package-name> </prefer-application-packages> </container-descriptor> </weblogic-web-app>
这样可以避免Weblogic自带的旧版本类覆盖应用中的类,导致配置不生效。
按照这些步骤逐一排查后,应该能解决你遇到的数据库操作错误。
内容的提问来源于stack exchange,提问作者shred22

