由于业务需求要求,在一个Service的一个方法A中有一个for循环,每次循环里面的业务逻辑有可能发生异常,这个时候就需要将这个循环内的所有数据库操作给回滚掉,但是又不能影响到之前循环里数据的更改,并且后面的循环里不发生异常的情况下也需要正常操作数据库
for (int i = 0; i < educationInfoArrayList.size(); i++) { String empCode = educationInfoArrayList.get(i).getEmpCode(); //导入员工信息的工号为自己下属时,则进行插入操作,否则跳过 EmployeeInfo ei = EmployeeUtils.getCurrentEmployeeInfo(); String myEmpCode = ei.getEmpNo(); List<String> subEmployeeList = getSubEmployeeList(myEmpCode); if(permission.equals("employee")) { if(!subEmployeeList.contains(empCode)) { numOfFailure +=1; uploadFailureInfo = new UploadFailureInfo(empCode, transformEmpCodeToEmpName(empCode), String.valueOf(numOfFailure), EMPLOYEE_IS_NOT_SUBORDINATE); uploadFailureInfoList.add(uploadFailureInfo); log.error("导入员工信息不为自己的下属"); continue; } } if(empCode.equals("") || empCode == null){ numOfFailure +=1; uploadFailureInfo = new UploadFailureInfo(empCode, "", String.valueOf(numOfFailure), EMPLOYEE_IS_NULL); uploadFailureInfoList.add(uploadFailureInfo); log.error("员工工号为空"); continue; } String result = insertOrUpdateByOnce(educationInfoArrayList.get(i), beforeEntryArrayList.get(i), afterEntryArrayList.get(i), educationExperienceArrayList.get(i), assessInfoArrayList.get(i), qualificationClassificationArrayList.get(i), trainingInfoArrayList.get(i)); if(!result.equals("success")){ numOfFailure +=1; uploadFailureInfo = new UploadFailureInfo(empCode, transformEmpCodeToEmpName(empCode), String.valueOf(numOfFailure), result); uploadFailureInfoList.add(uploadFailureInfo); continue; } }
@Transactional(rollbackFor = Exception.class) public String insertOrUpdateByOnce(EducationInfo educationInfo, BeforeEntry beforeEntry, AfterEntry afterEntry, EducationExperience educationExperience, AssessInfo assessInfo, QualificationClassification qualificationClassification, TrainingInfo trainingInfo) { try { //基本信息 Map<String, Object> paramMapBase = new HashMap<>(); paramMapBase.put("empCode", educationInfo.getEmpCode()); int queryBaseInformationCount = employeeDao.queryBaseInformationCount(paramMapBase); //插入或修改时出现错误 if(queryBaseInformationCount > 0){ employeeDao.updateBaseInformation(educationInfo); }else { employeeDao.addEducationInfo(educationInfo); } //入职神州前履历 Map<String, Object> paramMapBefore = new HashMap<>(); paramMapBefore.put("empCode", beforeEntry.getEmpCode()); paramMapBefore.put("startTime", beforeEntry.getStartTime()); int queryBeforeEntryCount = employeeDao.queryBeforeEntryCount(paramMapBefore); //插入或修改时出现错误 if(queryBeforeEntryCount > 0){ employeeDao.updateBeforeEntry(beforeEntry); }else { employeeDao.addBeforeEntry(beforeEntry); } //入职神州后履历 Map<String, Object> paramMapAfter = new HashMap<>(); paramMapAfter.put("empCode", afterEntry.getEmpCode()); paramMapAfter.put("startTime", afterEntry.getStartTime()); int queryAfterEntryCount = employeeDao.queryAfterEntryCount(paramMapAfter); //插入或修改时出现错误 if(queryAfterEntryCount > 0){ employeeDao.updateAfterEntry(afterEntry); }else { employeeDao.addAfterEntry(afterEntry); } //教育经历 Map<String, Object> paramMapEducation = new HashMap<>(); paramMapEducation.put("empCode", educationExperience.getEmpCode()); paramMapEducation.put("startTime", educationExperience.getStartTime()); int queryEducationExperienceCount = employeeDao.queryEducationExperienceCount(paramMapEducation); //插入或修改时出现错误 if(queryEducationExperienceCount > 0){ employeeDao.updateEducationExperience(educationExperience); }else { employeeDao.addEducationExperience(educationExperience); } //考核评价 Map<String, Object> paramMapExamine = new HashMap<>(); paramMapExamine.put("empCode", assessInfo.getEmpCode()); paramMapExamine.put("time", assessInfo.getTime()); int queryExamineCount = employeeDao.queryExamineCount(paramMapExamine); //插入或修改时出现错误 if(queryExamineCount > 0){ employeeDao.updateExamine(assessInfo); }else { employeeDao.addAssessInfo(assessInfo); } //资格分类 Map<String, Object> paramMapQualification = new HashMap<>(); paramMapQualification.put("empCode", qualificationClassification.getEmpCode()); paramMapQualification.put("getTime", qualificationClassification.getGetTime()); int queryQualificationClassificationCount = employeeDao.queryQualificationClassificationCount(paramMapQualification); //插入或修改时出现错误 if(queryQualificationClassificationCount > 0){ employeeDao.updateQualificationClassification(qualificationClassification); }else { employeeDao.addQualificationClassification(qualificationClassification); } //培训情况 Map<String, Object> paramMapTraining = new HashMap<>(); paramMapTraining.put("empCode", trainingInfo.getEmpCode()); paramMapTraining.put("time", trainingInfo.getTime()); int queryTrainingInfoCount = employeeDao.queryTrainingInfoCount(paramMapTraining); //插入或修改时出现错误 if(queryTrainingInfoCount > 0){ employeeDao.updateTrainingInfo(trainingInfo); }else { employeeDao.addTrainingInfo(trainingInfo); } } 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类中所有的方法都是执行事务的管理
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));
package com.ucarinc.inner.hrd.transactional; import com.ucarinc.inner.hrd.dao.EmployeeDao; import com.ucarinc.inner.hrd.model.employee.AfterEntry; import com.ucarinc.inner.hrd.model.employee.AssessInfo; import com.ucarinc.inner.hrd.model.employee.BeforeEntry; import com.ucarinc.inner.hrd.model.employee.EducationExperience; import com.ucarinc.inner.hrd.model.employee.EducationInfo; import com.ucarinc.inner.hrd.model.employee.QualificationClassification; import com.ucarinc.inner.hrd.model.employee.TrainingInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.util.HashMap; import java.util.Map; /** * description: * * @version 1.0 */ @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 { //基本信息 Map<String, Object> paramMapBase = new HashMap<>(); paramMapBase.put("empCode", educationInfo.getEmpCode()); int queryBaseInformationCount = employeeDao.queryBaseInformationCount(paramMapBase); //插入或修改时出现错误 if(queryBaseInformationCount > 0){ employeeDao.updateBaseInformation(educationInfo); }else { employeeDao.addEducationInfo(educationInfo); } //入职神州前履历 Map<String, Object> paramMapBefore = new HashMap<>(); paramMapBefore.put("empCode", beforeEntry.getEmpCode()); paramMapBefore.put("startTime", beforeEntry.getStartTime()); int queryBeforeEntryCount = employeeDao.queryBeforeEntryCount(paramMapBefore); //插入或修改时出现错误 if(queryBeforeEntryCount > 0){ employeeDao.updateBeforeEntry(beforeEntry); }else { employeeDao.addBeforeEntry(beforeEntry); } //入职神州后履历 Map<String, Object> paramMapAfter = new HashMap<>(); paramMapAfter.put("empCode", afterEntry.getEmpCode()); paramMapAfter.put("startTime", afterEntry.getStartTime()); int queryAfterEntryCount = employeeDao.queryAfterEntryCount(paramMapAfter); //插入或修改时出现错误 if(queryAfterEntryCount > 0){ employeeDao.updateAfterEntry(afterEntry); }else { employeeDao.addAfterEntry(afterEntry); } //教育经历 Map<String, Object> paramMapEducation = new HashMap<>(); paramMapEducation.put("empCode", educationExperience.getEmpCode()); paramMapEducation.put("startTime", educationExperience.getStartTime()); int queryEducationExperienceCount = employeeDao.queryEducationExperienceCount(paramMapEducation); //插入或修改时出现错误 if(queryEducationExperienceCount > 0){ employeeDao.updateEducationExperience(educationExperience); }else { employeeDao.addEducationExperience(educationExperience); } //考核评价 Map<String, Object> paramMapExamine = new HashMap<>(); paramMapExamine.put("empCode", assessInfo.getEmpCode()); paramMapExamine.put("time", assessInfo.getTime()); int queryExamineCount = employeeDao.queryExamineCount(paramMapExamine); //插入或修改时出现错误 if(queryExamineCount > 0){ employeeDao.updateExamine(assessInfo); }else { employeeDao.addAssessInfo(assessInfo); } //资格分类 Map<String, Object> paramMapQualification = new HashMap<>(); paramMapQualification.put("empCode", qualificationClassification.getEmpCode()); paramMapQualification.put("getTime", qualificationClassification.getGetTime()); int queryQualificationClassificationCount = employeeDao.queryQualificationClassificationCount(paramMapQualification); //插入或修改时出现错误 if(queryQualificationClassificationCount > 0){ employeeDao.updateQualificationClassification(qualificationClassification); }else { employeeDao.addQualificationClassification(qualificationClassification); } //培训情况 Map<String, Object> paramMapTraining = new HashMap<>(); paramMapTraining.put("empCode", trainingInfo.getEmpCode()); paramMapTraining.put("time", trainingInfo.getTime()); int queryTrainingInfoCount = employeeDao.queryTrainingInfoCount(paramMapTraining); //插入或修改时出现错误 if(queryTrainingInfoCount > 0){ employeeDao.updateTrainingInfo(trainingInfo); }else { employeeDao.addTrainingInfo(trainingInfo); } } catch (Exception e) { log.error("插入或者修改异常"); //失败则手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //返回异常信息 return e.getCause().getMessage(); } return "success"; } }
这样就符合事务管理的要求了
注解@Transactional(rollbackFor = Exception.class) 的用法
原文:https://www.cnblogs.com/liuqing576598117/p/10783821.html