异常记录:spring事务异常rollbackOnly

rollbackOnly通常发生在嵌套事务中
事务传播机制为默认Propagation.REQUIRED

A > X > X > X > B

A和B方法都有@Transactional注解,A中调用B,呈嵌套事务,公用一个事务(最外层A方法的事务)
当B发生异常时,Transactional会将当前rollbackOnly属性标记为true,因为异常被捕获(只要异常没有传到最外层的A),在处理结束A需要提交事务的时候,会执行JdbcResourceLocalTransactionCoordinatorImpl.commit()方法提交事务

@Override
		public void commit() {
			try {
				if ( rollbackOnly ) {
					log.debugf( "On commit, transaction was marked for roll-back only, rolling back" );

					try {
						rollback();

						if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
							log.debugf( "Throwing RollbackException on roll-back of transaction marked rollback-only on commit" );
							throw new RollbackException( "Transaction was marked for rollback-only" );
						}

						return;
					}
					catch (RollbackException e) {
						throw e;
					}
					catch (RuntimeException e) {
						log.debug( "Encountered failure rolling back failed commit", e );
						throw e;
					}
				}

				JdbcResourceLocalTransactionCoordinatorImpl.this.beforeCompletionCallback();
				jdbcResourceTransaction.commit();
				JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( true );
			}
			catch (RollbackException e) {
				throw e;
			}
			catch (RuntimeException e) {
				try {
					rollback();
				}
				catch (RuntimeException e2) {
					log.debug( "Encountered failure rolling back failed commit", e2 );
				}
				throw e;
			}
		}

commit()会检查当前是否被标记为rollbackOnly,否则抛出

throw new RollbackException( "Transaction was marked for rollback-only" );

解决办法:
1:保证同一个事务链的调用链没有出现捕获异常不抛出的情况
2:使用REQUIRES_NEW的隔离级别

我是因为采用了责任链模式,有点抽象,有一个不起眼环节异常被捕获而导致的

Propagation.REQUIRES_NEW

作用有两个
1:新开一个事务,外层事务不会影响内层事务的提交和回滚
2:如果内层事务出现异常,外层事务也会进行回滚

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值