因爲業務需求要求,在一個Service的一個方法A中有一個for循環,每次循環裏面的業務邏輯有可能發生異常,這個時候就須要將這個循環內的全部數據庫操做給回滾掉,可是又不能影響到以前循環裏數據的更改,而且後面的循環裏不發生異常的狀況下也須要正常操做數據庫java
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(),事務也沒有生效,且報錯spring
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"; } }
這樣就符合事務管理的要求了spa