关于Spring事务回滚记录

有两个service方法。 ServiceA的methodA的事务传播机制是:REQUIRED; ServiceB的methodB的事务传播机制是:REQUIRES_NEW。

外部REQUIRED
内部REQUIRES_NEW
测试结果:

  1. REQUIRES_NEW会新开启事务,外层事务不会影响内部事务的提交/回滚
  2. REQUIRES_NEW的内部事务的异常,会影响外部事务的回滚
//ServiceA中:REQUIRED
//**当这种情况methodB回滚,methodA也会回滚。因为B抛出异常,接着又传递到A中,A中接着抛了异常,所以A也回滚**
public void methodA(){
	insertA();
	methodB();
}

//ServiceB中:REQUIRES_NEW
public void  methodB(){
	insertB();
	int i = 1;
	i/0;
}

//这种情况B回滚,但是A不回滚。
public void  methodA(){
	insertA();
	try{
		methodB();
	}catch(){}
}




//ServiceA中:REQUIRED
//这种情况下,若methodB先执行了,下面再抛异常,B也不会再事务回滚
public void  methodA(){
	methodB();
	insertA();
	int i = 1;
	i/0;
	
}
ServiceB中:REQUIRES_NEW
public void  methodB(){
	insertB();
}

当A和B都是REQUIRED的时候,无论是否catch都会回滚


在一个Service中,有A和B两个方法。在A方法中调用B方法:

/**
这种情况B方法是否有具有事务是有A方法决定的
1、当A方法有事务,那么B方法也会有相应的事务
2、当A方法没有事务,无论B方法是否有事务,B的事务都不会生效
这是由于AOP代理机制决定的
如果想让B事务生效可以这样写:
1.在spring配置文件中添加如下配置:
	<aop:aspectj-autoproxy expose-proxy="true"/>
expose-proxy:默认false, 目标对象内部的自我调用将无法实施切面中的增强(代理对象),
设置成true以后,我们就能在同一个service中拿到这个自己的代理对象。
2.代码这样写:((Service) AopContext.currentProxy()).B();
*/
public class Service{

	public void A(){
		this.B();
	}
	@Transcation
	public void B(){
	}
}
/**
srping事务就是springAOP的体现,事务可以认为对方法本身的一种加强,那么要开启这种加强,就要代理对象,那么大家看上述代码,
methodA()中methodB被谁调用呢?是this!!(同类中不同方法的调用默认就是this)也就是目标对象,
并不是代理对象,也就不能使用AOP代理,所以事务就不会生效

**/


事务总结:

1、两者都是REQUIRED 当ServiceB().B()抛异常时,A()和B()两个事务都会回滚,并抛出:UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
2、A是REQUIRED,B是REQUIRES_NEW 当ServiceB().B()抛异常时,B()回滚而A()不会回滚

	public void ServiceA(){
		public void A(){
			insertA();
			try{
				ServiceB().B();
			}catch(Exception e){
			
			}
		}
	}
	public void ServiceB(){
		public void B(){
			insertB();
			int i = 1/0;
		}
	}

3、两者都是REQUIRED执行完insertA()和ServiceB().B()后,抛异常:两者都回滚,因为两者是同一事务
4、A是REQUIRED,B是REQUIRES_NEW:执行完insertA()和ServiceB().B()后,抛异常:A会回滚,而B不会回滚,因为两者不是同一事务

	public void ServiceA(){
		public void A(){
			insertA();
			ServiceB().B();
			int i = 1/0;
		}
	}
	public void ServiceB(){
		public void B(){
			insertB();
		}
	}

5、同一个ServiceA中,A()调用B(), a、当A()无事务,B()有事务时:这时候B()事务不会生效, b、当A()添加REQUIRED,B()不添加事务时:B会加入A的事务中,所以都会回滚 c、当A()添加RREQUIRES_NEW,B()不添加事务时:同b情况 以上其实是一种情况:B()的事务是跟随A()的事务 因为srping事务就是springAOP的体现,事务可以认为对方法本身的一种加强,那么要开启这种加强,就要代理对象, 那么大家看代码,A()中的B()被谁调用呢?是this!!(同类中不同方法的调用默认就是this)也就是目标对象, 并不是代理对象,也就不能使用AOP代理,自然就开启不了事务,B()的事务自然不会生效

	public void ServiceA(){
		public void A(){
			insertA();
			try{
				B()}catch(Exception e){	
			}
		}
		public void B(){
			insertA();
			int i = 1/0;
		}
	}

6、如果想让B()事务生效需要进行两处修改: a、配置文件添加<aop:aspectj-autoproxy expose-proxy="true"/> b、((ServiceA) AopContext.currentProxy()).B(); 这样A()和B()的事务配置都会生效,就如何A()和B()是在两个Service中一样

	public void ServiceA(){
		public void A(){
			insertA();
			try{
				((ServiceA) AopContext.currentProxy()).B();
			}catch(Exception e){	
			}
		}
		public void B(){
			insertA();
			int i = 1/0;
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值