@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();
    }

}

结束