有两个service方法。 ServiceA的methodA的事务传播机制是:REQUIRED; ServiceB的methodB的事务传播机制是:REQUIRES_NEW。
外部REQUIRED
内部REQUIRES_NEW
测试结果:
- REQUIRES_NEW会新开启事务,外层事务不会影响内部事务的提交/回滚
- 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;
}
}