由於業務需求要求,在一個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"; } }
這樣就符合事務管理的要求了