关于事务之间的调用产生的回滚问题

关于事务之间的调用产生的回滚问题

//以下self()均看做AopContext.currentProxy()–》走代理路线!!,为的是在同一类两个事务方法生效(最后有说明)

/**REQUIRED方法调用REQUIRED方法*/
//1.子方法抛出异常,父方法不处理,都会回滚----》updateA()回滚,updateB()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  self().updateSon();
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
  updateB();
  throw new Exception("手动给子方法抛出异常");
}

//2.子方法抛出异常,父方法处理异常,都会回滚---》updateA()回滚,updateB()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  try{
  self().updateSon();
  }catch(Exception e){
   logger.info("对子事务异常进行处理,但不抛出")
  }
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
  updateB();
  throw new Exception("手动给子方法抛出异常");
}

//3.子方法无异常,父方法有异常但不处理,都会回滚---》updateA()回滚,updateB()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  self().updateSon();
  throw new Exception("手动给父方法抛出异常");
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
  updateB();
}

总结:REQUIRED总是会在一个事务中,无论哪个位置抛出异常,均会全部回滚,即使对子方法异常进行了处理,还是会全部回滚。另外,如果在子方法中对异常进行了处理,相当于没有异常,事务均不会回滚。因为异常只有在抛出去后才会触发事务,如果进行了处理是不会触发事务的,如下:

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  self().updateSon();
}


@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateSon() throws Exception {
  updateB();
  //以下try catch相当于没有异常,不会触发事务
  try{
    throw new Exception("手动给子方法抛出异常");
  }catch(Exception e){
    logger.info("对子事务异常进行了处理") ; 
 }

}
/**REQUIRED调用NESTED*/
//1.子方法第二次抛出异常,父方法未处理该异常,均会回滚---》 updateA(),updateB(),updateC()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  for(int i=0;i<2;i++){
  self().updateSon(i);
 }
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
public void updateSon(int i) throws Exception {
if(i=0){
  updateB();
}
if(i=1){
  updateC();
  throw new Exception("手动给子方法抛出异常");
}
}

//2.子方法第二次抛出异常,父方法处理异常,已经执行的不会回滚---》updateA(),updateB()不会回滚,updateC()回滚。
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  for(int i=0;i<2;i++){
try{
  self().updateSon(i);
}catch(Exception e){
 logger.info("处理子事务异常但不抛出");
}
}


@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
public void updateSon(int i) throws Exception {
if(i=0){
  updateB();
}
if(i=1){
  updateC();
  throw new Exception("手动给子方法抛出异常");
}
}
//3.子方法无异常,父方法在第二次循环的时候抛出异常,均会回滚---》updateA(),updateB(),updateC()均回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  for(int i=0;i<2;i++){
  self().updateSon(i);
  if(i==1){
    throw new Exception("执行第二次循环的时候在父方法抛出异常");
    }
  }
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
public void updateSon(int i) throws Exception {
if(i=0){
  updateB();
}
if(i=1){
  updateC();
}
}

总结:NESTED会跟随父事务一起提交,如果父事务一旦出现异常,均会回滚,但如果NESTED子方法事务出现异常,父事务对其进行了处理,已经执行的不会回滚(如代码2)。

/**REQUIRED调用REQUIRES_NEW*/
//1.子方法第二次抛出异常,父方法未处理该异常,部分回滚---》 updateA(),updateC()回滚,updateB()不回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  for(int i=0;i<2;i++){
  self().updateSon(i);
}
}


@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateSon(int i) throws Exception {
if(i=0){
  updateB();
}
if(i=1){
  updateC();
  throw new Exception("手动给子方法抛出异常");
}
}

//2子方法第二次抛出异常,父方法处理异常--》updateA()不回滚,updateB(),updateC()回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  for(int i=0;i<2;i++){
try{
  self().updateSon(i);
}catch(Exception e){
logger.info("处理子事务异常但不抛出");
}
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateSon(int i) throws Exception {
if(i=0){
  updateB();
}
if(i=1){
  updateC();
  throw new Exception("手动给子方法抛出异常");
}
}
//3.子方法无异常,父方法在第二次循环的时候抛出异常---》updateA()回滚,updateB(),updateC()不回滚
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void updateFather() throws Exception {
  updateA();
  for(int i=0;i<2;i++){
  self().updateSon(i);
  if(i==1){
    throw new Exception("执行第二次循环的时候在父方法抛出异常");
    }
  }
}

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updateSon(int i) throws Exception {
if(i=0){
  updateB();
}
if(i=1){
  updateC();
}
}

总结:REQUIRES_NEW新开一个事务,与父事务相互隔离,互不影响。

另外::如果同一个类中有两个事务方法A,B,事务方法A调用事务方法B,B事务方法是不会生效的,因为这样是不走代理类调用的,要想事务奏效必须使用代理类调用。针对此问题有两种方法可以解决
1.将B事务方法放到另外一个类中,通过注入类来进行调用
2.使用AopContext.currentProxy()来进行调用,即在A事务方法中调用B事务方法代码为:(该类名)AopContext.currentProxy().B();(以上self()就是 AopContext.currentProxy()!!,)

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值