Bootstrap

@Transactional和try...catch一起使用、嵌套使用

结论
结论一:对于@Transactional可以保证RuntimeException错误的回滚,如果想保证非RuntimeException错误的回滚,需要加上rollbackFor = Exception.class 参数。

结论二:try catch只是对异常是否可以被@Transactional 感知 到有影响。如果错误抛到切面可以感知到的地步,那就可以起作用。即如果只是catchd缺没有抛出来,那么注解无效

结论三:由于REQUIRED属性,“两个事务”其实是一个事务,处理能力看报错时刻,是否添加了处理非RuntimeException的能力。即事务嵌套的时候,如果发现已经有事务存在了,就加入这个事务,而不是新建一个事务,所以根本就不存在两个事务,一直只有一个!
如:

@GetMapping("/out")
@Transactional
public void out() throws Exception{
    innerService.inner();
    int age = random.nextInt(100);
    User user = new User().setAge(age).setName("name:" + age);
    userService.save(user);
}
@Transactional( rollbackFor = Exception.class)
public void inner() throws Exception{
    Role role = new Role();
    role.setRoleName("roleName:"+new Random().nextInt(100));
    roleService.save(role);
    throw new Exception();
}

上面代码会回滚。

 @GetMapping("/out")
 @Transactional
 public void out() throws Exception{
     innerService.inner();
     int age = random.nextInt(100);
     User user = new User().setAge(age).setName("name:" + age);
     userService.save(user);
     throw new Exception();
 }
    
 @Transactional( rollbackFor = Exception.class)
 public void inner() throws Exception{
     Role role = new Role();
     role.setRoleName("roleName:"+new Random().nextInt(100));
     roleService.save(role);
 }

这里代码不会回滚。

!!!但是!!!
如果在out方法try…catch…住了inner,导致@Transactional没有接收到异常,那么回滚将都不起作用。(待测试)

所以可以通过再catch里加入这个进行手动回滚:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

;