Spring对待事物的实现有一个标签可以使用@Transactional标签来实现事务的管理,但是在使用的时候很多人不清楚实现的原理而使用了错误的使用方式,导致日志里的确是打印了,但是方法的确没有回滚。
我在遇到问题的时候发生了这样的问题,就先去了解下Java中导致程序出现的情况都有哪些
首先Java中的将会导致程序出错的各种情况统称为Throwable,它有两个重要的子类:Exception和Error,二者都是Java异常处理的重要类。
Error是程序已无法处理的异常,与程序员编码无关,是JDK内部出现的问题,一般都是很严重的错误。
Exception是程序自身能处理的异常。
这些异常基本都是可以在编译器发现的,但是除了Exception的一个子类叫做RunTimeException,这个异常只有在运行的过程中才会出现,我们的Try/catch语句,就是为了捕获这种RunimeException,并且处理它,然而我们应该已经被处理的异常是不会再向上抛出的,因为我们已经在这层解决好了,所以一般我们会继承Exception类,把遇到的异常抛出,从而使得Spring的事务管理机制可以捕获到异常,然后回滚。
所以说我们在使用@Transactional进行实现事务的时候,尽量不用Try/catch语句,把异常向上抛出即可。
在别人的博客上我看到了一段代码可以让我很好的理解 :
这段代码,因为已经处理了异常,所以Spring的事务就捕获不到异常信息,导致事务回滚失败
- if(userSave){
- try {
- userDao.save(user);
- userCapabilityQuotaDao.save(capabilityQuota);
- } catch (Exception e) {
- logger.info("能力开通接口,开户异常,异常信息:"+e);
- }
- }
下面的这种情况,当一个方法出错,抛出一个异常,另一个方法就会回滚:
使用throws关键字把try/catch捕获的异常再一次抛出去
- if(userSave){
- try {
- userDao.save(user);
- userCapabilityQuotaDao.save(capabilityQuota);
- } catch (Exception e) {
- logger.info("能力开通接口,开户异常,异常信息:"+e);
- throw new RuntimeException();
- }
- }
- if(userSave){
- try {
- userDao.save(user);
- userCapabilityQuotaDao.save(capabilityQuota);
- } catch (Exception e) {
- logger.info("能力开通接口,开户异常,异常信息:"+e);
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
- }
- }