SpirngBoot Transactional 处理

在SpingBoot下使用事务很简单只要在class或function的上打个标签 @Transactional 就可以了。

Transactional 是Sring AOP去管理的,这个很重要,所有的坑都是因为不了解这个才会踩下去。但好多同学其实跟我一样对AOP不怎么了解的,所以我把我走过的坑都分享一下。

 

下面是我走过的坑。

1. @Transactional 标签可以打在class上,也可以打在function上,function的话必须为public,而且这个function是被其它class掉用才会生效。简单说就是,如果在class内的function互相调用就别妄想事务会回滚

2. 关于回滚的触发是方法抛出RuntimeException,并且RuntimeException未被捕获,这个时候就会自己回滚,如果你使用了try-catch,异常都被catch了,你就别妄想事务会回滚

3. 真的想在catch里面自己回滚吗,还是有的,你必须抛出RuntimeException,如果抛出的是Exception,则需要使用@Transactional(rollbackFor=Exception.class)处理指定的Excetption

4. 你不要抛出异常但也要回滚?还是有的,你就要手动回滚:“ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); ”;

5. 有没有同学像我一样,在回滚以后还要写数据库记录失败的状态,我要说明一下,回滚是切面回滚,即使你在rollback后面的代码也是不生效的;

6. 针对这一点,我用了一个很简单的解决思路,在这个打上@Transactional 标签的class里面加一个方法去处理failed的方法就好;
    因为需要回滚的方法必须是被其它类调用才能触发事务,所以在调用它的地方你可以用try-catch,在捕获Excetption以后再调用failed方法就好了;

7. 其实还有一个参数是可以选择的@Transactional (propagation=Propagation.REQUIRES_NEW), 把这个标签打在failed上面就可以了

 

我还是写个Demo吧:

1. 什么都不做,最简单的事务处理

package org.bts.services;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class TransactionalService {
    public void save() {
        
    }
    
    public void failed() {
        
    }
}
package org.bts.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class TransactionalDemo {
    @Autowired
    private TransactionalService service;
    
    public void demo() {
        try {
            service.save();
        } catch (Exception e) {
            e.printStackTrace();
            service.failed();
        }
    }
}

以上这个其实save里面就会自己动做回滚了

2. 如果你要用try-catch, 以下为三种处理方式

package org.bts.services;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class TransactionalService {
    public void Save() {
        try {
            
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
    
    public void failed() {
        
    }
}
package org.bts.services;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Service
@Transactional
public class TransactionalService {
    public void Save() {
        try {
            
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    
    public void failed() {
        
    }
}
package org.bts.services;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor=Exception.class)
public class TransactionalService {
    public void Save() {
        try {
            
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
    
    public void failed() {
        
    }
}

 3.使用Propagation.REQUIRES_NEW

package org.bts.services;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor=Exception.class)
public class TransactionalService {
    public void Save() {
        try {
            
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            failed();
        }
    }
    
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void failed() {
        
    }
}    

 

posted on 2018-08-03 11:42  BadTree  阅读(288)  评论(0编辑  收藏  举报