spring事务(3)-----事务传播行为详解

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html

我们通过一张图引入

这个怎么实现呢?

我们来看这7中传播行为

Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 

PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 

PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 

PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

 

 至于事务的传播入门请看

spring事物(2)-----手写spring注解事务&&事务传播行为

 

下面我们来仔细分析上面的7中行为。

假设有类A的方法methodB(),有类B的方法methodB()。A.methodA()调用B的methodB()方法。这里A.methodA()就是 UserService.add()   B.methodB()就是logService.addLog();

一,传播机制1-----PROPAGATION_REQUIRED  Transactional默认的

A.methodA()调用B的methodB()方法,那么如果A的方法包含事务,则B的方法则不从新开启事务,

 

1、  如果B的methodB()抛出异常,A的methodB()没有捕获,则A和B的事务都会回滚;

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    @Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);

    }        
    }
    
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}

2、如果B的methodB()运行期间异常会导致B的methodB()的回滚,A如果捕获了异常,并正常提交事务,则会发生Transaction rolled back because it has been marked as rollback-only的异常。

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    @Transactional
    public void add() {
        try{
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);
        }catch{            
        }
    }        
    }
    
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}

3、如果A的methodA()运行期间异常,则A和B的Method的事务都会被回滚

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    @Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();
        int i = 1 / 0;        
        userDao.add("test002", 21);
    }        
    }
    
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
    }
}

 

二,传播机制2----- PROPAGATION_SUPPORTS


如果B的方法methodB()的事务传播特性是propagation_supports,
A.methodA()调用B的methodB()方法,那么如果A的方法包含事务,则B运行在此事务环境中,如果A的方法不包含事务,则B运行在非事务环境;

1、如果A没有事务,则A和B的运行出现异常都不会回滚。

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();
        int i = 1 / 0;        
        userDao.add("test002", 21);
    }        
    }
    @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
    }
}

 

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();            
        userDao.add("test002", 21);
    }        
    }
    
    @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
        int i = 1 / 0;    
    }
}

 

 

2、如果A有事务,A的method方法执行抛出异常,B.methodB和A.methodA都会回滚。

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    @Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();
        int i = 1 / 0;        
        userDao.add("test002", 21);
    }        
    }
    @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
    }
}

3、如果A有事务,B.method抛出异常,B.methodB和A.methodA都会回滚,如果A捕获了B.method抛出的异常,则会出现异常Transactionrolled back because it has been marked as rollback-only。

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    @Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);

    }        
    }
    
    @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}
@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    @Transactional
    public void add() {
        try{
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);
        }catch{            
        }
    }        
    }
    @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }
}

三,传播机制3----- PROPAGATION_MANDATORY

表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常,如下图调用关系:

B.methodB()事务传播特性定义为:PROPAGATION_MANDATORY

 

1、如果A的methoda()方法没有事务运行环境,则B的methodB()执行的时候会报如下异常:No existingtransaction found for transaction marked with propagation 'mandatory'

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    

    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);

    }        
    }
    
    @Transactional(propagation = Propagation.PROPAGATION_MANDATORY)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}

 

2、如果A的Methoda()方法有事务并且执行过程中抛出异常,则A.methoda()和B.methodb()执行的操作被回滚;

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
    @Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();    
 int i = 1 / 0;        
        userDao.add("test002", 21);

    }        
    }
    
    @Transactional(propagation = Propagation.PROPAGATION_MANDATORY)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
        
    }

}

3、如果A的methoda()方法有事务,则B.methodB()抛出异常时,A的methoda()和B.methodB()都会被回滚;如果A捕获了B.method抛出的异常,则会出现异常Transaction rolled back because ithas been marked as rollback-only

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
 @Transactional
    public void add() {

        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);

    }        

    
    @Transactional(propagation = Propagation.PROPAGATION_MANDATORY)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}
@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
 @Transactional
    public void add() {
        try{
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);
        }catch{
        }
    }        

    
    @Transactional(propagation = Propagation.PROPAGATION_MANDATORY)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}

四,传播机制4----- PROPAGATION_NESTED

 

B的methodB()定义的事务为PROPAGATION_NESTED;

 

 

1、如果A的MethodA()不存在事务,则B的methodB()运行在一个新的事务中,B.method()抛出的异常,B.methodB()回滚,但A.methodA()不回滚;如果A.methoda()抛出异常,则A.methodA()和B.methodB()操作不回。

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    

    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();        
        userDao.add("test002", 21);

    }        
    }
    
    @Transactional(propagation = Propagation.PROPAGATION_NESTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i = 1 / 0;
    }

}
@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    

    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();
int i = 1 / 0;        
        userDao.add("test002", 21);

    }        
    }
    
    @Transactional(propagation = Propagation.PROPAGATION_NESTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         
    }

}

2、如果A的methodA()存在事务,则A的methoda()抛出异常,则A的methoda()和B的Methodb()都会被回滚;

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();
int i = 1 / 0;        
        userDao.add("test002", 21);

    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_NESTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         
    }

}

3、如果A的MethodA()存在事务,则B的methodB()抛出异常,B.methodB()回滚,如果A不捕获异常,则A.methodA()和B.methodB()都会回滚,如果A捕获异常,则B.methodB()回滚,A不回滚;

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();    
        userDao.add("test002", 21);

    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_NESTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
        int i = 1 / 0;    
         
    }

}
@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        try{
        userDao.add("test001", 20);   
        logService.addLog();    
        userDao.add("test002", 21);
        }catch{
        }

    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_NESTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
        int i = 1 / 0;    
         
    }

}


五,传播机制5----- PROPAGATION_NEVER

 

 

表示事务传播特性定义为PROPAGATION_NEVER的方法不应该运行在一个事务环境中

 

 

 如果B.methodB()的事务传播特性被定义为PROPAGATION_NEVER,则如果A.methodA()方法存在事务,则会出现异常Existingtransaction found for transaction marked with propagation 'never'。

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        try{
        userDao.add("test001", 20);   
        logService.addLog();    
        userDao.add("test002", 21);
        }catch{
        }

    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_NEVER)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
        int i = 1 / 0;    
         
    }

}

六,传播机制6----- PROPAGATION_REQUIRES_NEW

 

 表示事务传播特性定义为PROPAGATION_REQUIRES_NEW的方法需要运行在一个新的事务中。

如有一下调用关系:B.methodB()事务传播特性为PROPAGATION_REQUIRES_NEW.

 

 

1、如果A存在事务,A.methodA()抛出异常,A.methodA()的事务被回滚,但B.methodB()事务不受影响;
如果B.methodB()抛出异常,A不捕获的话,A.methodA()和B.methodB()的事务都会被回滚。
如果A捕获的话,A.methodA()的事务不受影响但B.methodB()的事务回滚。

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();    
        int i=1/0;
        userDao.add("test002", 21);
    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         
    }
}

如果B.methodB()抛出异常,A不捕获的话,A.methodA()和B.methodB()的事务都会被回滚。

 

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();    
        userDao.add("test002", 21);
    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i=1/0;
    }

}

如果A捕获的话,A.methodA()的事务不受影响但B.methodB()的事务回滚。

 

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        try{
        userDao.add("test001", 20);   
        logService.addLog();    

        userDao.add("test002", 21);
        }catch{
        }

    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
                 int i=1/0;
    }

}

七,传播机制7----- PROPAGATION_NOT_SUPPORTED

 

表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行。

如有一下调用关系图:

如果B.methodB()方法传播特性被定义为:PROPAGATION_NOT_SUPPORTED。

 

1、如果A.methodA()存在事务,如果B.methodB()抛出异常,A.methodA()不捕获的话,A.methodA()的事务被回滚,而B.methodB()出现异常前数据库操作不受影响。如果A.methodA()捕获的话,则A.methodA()的事务不受影响,
B.methodB()异常抛出前的数据操作不受影响。

@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
        userDao.add("test001", 20);   
        logService.addLog();    
        userDao.add("test002", 21);
    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_NOT_SUPPORTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i=1/0;
    }

}
@Service
public class UserServiceImplc implements UserService {
    @Autowired
    private UserDaoc userDao;
    @Autowired
    private LogService logService;
    
@Transactional
    public void add() {
    try{
        userDao.add("test001", 20);   
        logService.addLog();    
        userDao.add("test002", 21);}catch{
        }
    }        

}
    @Transactional(propagation = Propagation.PROPAGATION_NOT_SUPPORTED)
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void addLog() {
        logDao.add("addLog" + System.currentTimeMillis());
         int i=1/0;
    }

}

 

八,事务的使用案例 

1、  在一个话费充值业务处理逻辑中,有如下图所示操作:

业务需要扣款操作和创建订单操作同成功或者失败,因此,charger()和order()的事务不能相互独立,需要包含在chargeHandle()的事务中;

通过以上需求,可以给charge()和order()的事务传播行为定义成:PROPAGATION_MANDATORY

只要charge()或者order()抛出异常整个chargeHandle()都一起回滚,即使chargeHandle()捕获异常也没用,不允许提交事务。

2、  如果业务需求没接受到一次请求到要记录日志到数据库,如下图:

 

因为log()的操作不管扣款和创建订单成功与否都要生成日志,并且日志的操作成功与否不影响充值处理,所以log()方法的事务传播行为可以定义为:PROPAGATION_REQUIRES_NEW.

3、  在订单的售后处理中,更新完订单金额后,需要自动统计销售报表,如下图所示:

 

根据业务可知,售后是已经处理完订单的充值请求后的功能,是对订单的后续管理,统计报表report()方法耗时较长,因此,我们需要设置report()的事务传播行为为:PROPAGATION_NEVER,表示不适合在有事务的操作中调用,因为report()太耗时。

4、  在银行新增银行卡业务中,需要执行两个操作,一个是保存银行卡信息,一个是登记新创建的银行卡信息,其中登记银行卡信息成功与否不影响银行卡的创建。

 

 

 

由以上需求,我们可知对于regster()方法的事务传播行为,可以设置为PROPAGATION_NESTED,action()事务的回滚,regster()保存的信息就没意义,也就需要跟着回滚,而regster()的回滚不影响action()事务;insert()的事务传播行为可以设置为PROPAGATION_REQUIRED, PROPAGATION_MANDATORY,即insert()回滚事务,action()的事务必须跟着回滚。

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值