Spring 4.x升级至5.3.x遇No Connection Holder可用错误,咨询TransactionProxyFactoryBean变更
Spring 5.3.x升级后Apache OJB出现No ConnectionHolder available问题解析
问题概述
Spring从4.x升级到5.3.x后,搭配Apache OJB作为ORM框架时触发No ConnectionHolder available异常,相关配置与错误栈如下:
配置代码
<bean id="testBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="target"> <ref bean="TestTarget"/> </property> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="update*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="save*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="delete*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
错误栈
java.lang.IllegalStateException: No ConnectionHolder available at org.springframework.util.Assert.state(Assert.java:76) ~[spring-core-5.3.25.jar:5.3.25] at org.springframework.jdbc.datasource.JdbcTransactionObjectSupport.getConnectionHolder(JdbcTransactionObjectSupport.java:76) ~[spring-jdbc-5.3.25.jar:5.3.25] at org.springmodules.orm.ojb.PersistenceBrokerTransactionManager$PersistenceBrokerTransactionObject.isRollbackOnly(PersistenceBrokerTransactionManager.java:230) ~[classes/:?]
TransactionProxyFactoryBean在Spring 5的变更
首先明确:TransactionProxyFactoryBean在Spring 5中并未被移除,但已被标记为过时(deprecated),官方推荐使用注解式事务(@Transactional)或ProxyFactoryBean + TransactionInterceptor的组合替代。不过这不是直接触发异常的原因,核心问题在于Spring 5事务底层逻辑的调整与Apache OJB的兼容性冲突。
关键底层变更
- ConnectionHolder断言检查强化:Spring 5中
JdbcTransactionObjectSupport.getConnectionHolder()新增了严格断言,当线程上下文无可用ConnectionHolder时直接抛出IllegalStateException;而Spring 4.x中处理更宽松,可能仅返回null,OJB的PersistenceBrokerTransactionManager未适配这一严格校验。 - 事务同步生命周期调整:Spring 5优化了事务同步上下文的管理逻辑,OJB的事务管理器未正确参与到新的同步流程中,导致ConnectionHolder未被绑定到当前线程。
修复方案
1. 替换过时的TransactionProxyFactoryBean
改用ProxyFactoryBean结合TransactionInterceptor配置事务代理,示例:
<bean id="testBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="TestTarget"/> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="update*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="save*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="delete*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
2. 适配OJB事务管理器
如果使用SpringModules提供的PersistenceBrokerTransactionManager,该模块已停止维护,需自行扩展或修改其实现,确保在事务初始化阶段将ConnectionHolder正确绑定到线程上下文。例如,重写doBegin方法,显式设置ConnectionHolder。
3. 迁移到注解式事务管理(推荐)
这是Spring官方主推的方案,步骤如下:
- 在XML配置中启用注解驱动:
<tx:annotation-driven transaction-manager="transactionManager"/> - 在业务方法/类上添加
@Transactional注解:import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Isolation; @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) public void insertEntity(Entity entity) { // OJB持久化逻辑 } @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public Entity getEntityById(Long id) { // OJB查询逻辑 }
内容的提问来源于stack exchange,提问作者Qrios
相关产品推荐
相关产品推荐

