@ApiOperation(value = "事务测试") @PostMapping(value="/test/transactional") @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED) public String testTransactional(){ Date currentDate = new Date(); Boolean hasC = false; if(hasC){ throw new RuntimeException("参数错误"); } //向数据库插入一条记录C Boolean hasB = true; if(hasB){ throw new RuntimeException("参数错误"); } //向数据库插入一条记录B return "succeee"; }
只有当@Transactional注解和RuntimeException异常配合使用,才能使事务生效。
@ApiOperation(value="事务测试") @PostMapping(value="/test/transactional") public String testTransactional(){ try{ insertUsers(); return "success"; }catch(RuntimeException e){ log.error("异常:",e); return "error"; } } @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED) void insertUsers(){ Date currentDate = new Date(); Boolean hasC = false; if(hasC){ throw new RuntimeException("参数错误"); } //向数据库插入一条记录C Boolean hasB = true; if(hasB){ throw new RuntimeException("参数错误"); } //向数据库插入一条记录B }
而以上代码事务是不生效的。
使用手动事务回滚的方式:
1、必须要有@Transactional注解,但是不需要RuntimeException异常了。
2、TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@ApiOperation(value="事务测试") @PostMapping(value="/test/transactional") @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED) public String testTransactional(){ try{ String result = insertUsers(); if("参数错误".equals(result)){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } return result ; }catch(Exception e){ log.error("异常:",e); return "error"; } } String insertUsers(){ Date currentDate = new Date(); Boolean hasC = false; if(hasC){ return "参数错误"; } //向数据库插入一条记录C Boolean hasB = true; if(hasB){ return "参数错误"; } //向数据库插入一条记录B return "success"; }
测试对Redis是否生效
@ApiOperation(value="事务测试") @PostMapping(value="/test/transactional") @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED) public String testTransactional(){ try{ redisUtil.set("AA000011","AA000011",3600); String result = insertUsers(); if("参数错误".equals(result)){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } redisUtil.set("AA000022","AA000022",3600); return result ; }catch(Exception e){ log.error("异常:",e); return "error"; } } String insertUsers(){ Date currentDate = new Date(); Boolean hasC = false; if(hasC){ return "参数错误"; } //向数据库插入一条记录C Boolean hasB = true; if(hasB){ return "参数错误"; } //向数据库插入一条记录B return "success"; }
测试发现:对于redis的键AA000011和AA000022都进行了回滚。
为什么AA000022也进行了回滚?
分析认为,@Transactional是注解在方法上的,所以此方法就是一个原子性的事务,当执行手动回滚代码的时候,只要是在这个方法中的逻辑或这个原子中的逻辑,都没有生效。
springboot中使用通知的方式进行事务的回滚:
pom中导入
<!--增加AOP需要的包--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
@Aspect @Component public class MyAspect { // @After(value = "execution(* com.company.ant.api.controller.TestController.testTransactional(..))") // public void after(){ // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // } @AfterReturning(returning = "rev", value = "execution(* com.company.ant.api.controller.TestController.testTransactional(..))") public void after(Object rev){ //后置通知获取目标对象返回结果--CommonResult{code=10001, msg='参数异常', data={}} log.info("后置通知获取目标对象返回结果--" + rev); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } }
结束
浙公网安备 33010602011771号