注解@Transactional(rollbackFor = Exception.class) 的用法


由於業務需求要求,在一個Service的一個方法A中有一個for循環,每次循環里面的業務邏輯有可能發生異常,這個時候就需要將這個循環內的所有數據庫操作給回滾掉,但是又不能影響到之前循環里數據的更改,並且后面的循環里不發生異常的情況下也需要正常操作數據庫

for (int i = 0; i < educationInfoArrayList.size(); i++) {
    String result = insertOrUpdateByOnce(educationInfoArrayList.get(i), beforeEntryArrayList.get(i), afterEntryArrayList.get(i), educationExperienceArrayList.get(i),
            assessInfoArrayList.get(i), qualificationClassificationArrayList.get(i), trainingInfoArrayList.get(i));
}

@Transactional(rollbackFor = Exception.class)
public String insertOrUpdateByOnce(EducationInfo educationInfo, BeforeEntry beforeEntry, AfterEntry afterEntry, EducationExperience educationExperience, AssessInfo assessInfo,
        QualificationClassification qualificationClassification, TrainingInfo trainingInfo) {

    try {
        //這里寫核心業務方法
    } catch (Exception e) {
        log.error("插入或者修改異常");
        //失敗則手動回滾
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        //返回異常信息
        return e.getCause().getMessage();
    }

    return "success";

}

catch中加上手動回滾 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),事務也沒有生效,且報錯

org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope
    at org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(TransactionAspectSupport.java:122)
    at com.dubboconsumer.dubboConsumer.service.imp.DemoService.B(DemoService.java:44)
    at com.dubboconsumer.dubboConsumer.service.imp.DemoService.A(DemoService.java:20)
    at com.dubboconsumer.dubboConsumer.service.imp.DemoService$$FastClassBySpringCGLIB$$c7449c96.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:669)
    ...

原因是:調用了同一個類的方法,給這個方法配上事務注解是不會生效的,這個類里面沒有事務,不能進行手動回滾;Spring之所以可以對開啟@Transactional的方法進行事務管理,是因為Spring為當前類生成了一個代理類,然后在執行相關方法時,會判斷這個方法有沒有@Transactional注解,如果有的話,則會開啟一個事務;所以,要把執行事務的方法全部丟到一個service類,在這個service類上配上注解@Transactional(rollbackFor = Exception.class),則這個service類中所有的方法都是執行事務的管理

 

for (int i = 0; i < educationInfoArrayList.size(); i++) {
    String result = insertOrUpdateEmployeeService.insertOrUpdateByOnce(educationInfoArrayList.get(i), beforeEntryArrayList.get(i), afterEntryArrayList.get(i), educationExperienceArrayList.get(i),
                    assessInfoArrayList.get(i), qualificationClassificationArrayList.get(i), trainingInfoArrayList.get(i));
}

 

@Repository
@Transactional(rollbackFor = Exception.class)
public class InsertOrUpdateEmployeeService {

    private static final Logger log = LoggerFactory.getLogger(InsertOrUpdateEmployeeService.class);

    @Autowired
    private EmployeeDao employeeDao;

    public String insertOrUpdateByOnce(EducationInfo educationInfo, BeforeEntry beforeEntry, AfterEntry afterEntry, EducationExperience educationExperience, AssessInfo assessInfo,
                                       QualificationClassification qualificationClassification, TrainingInfo trainingInfo) {

        try {
            //這里寫核心業務方法
        } catch (Exception e) {
            log.error("插入或者修改異常");
            //失敗則手動回滾
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            //返回異常信息
            return e.getCause().getMessage();
        }

        return "success";

    }
}

這樣就符合事務管理的要求了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM