异常捕获与事务

1,588 阅读1分钟

1.事务回滚

普通的@Transactional()注解,只能回滚RuntimeException异常,对于非RuntimeException则无法回滚,所以如果我们需要非RuntimeException异常也能进行回滚的话,我们可以加上@Transactional(rollbackFor = Exception.class)

2.try catch以后,事务还能正常回滚吗?

在我们实际开发中,service中的异常我们大多需要手动去捕获,那么这个时候事务还会生效吗?我们来做个试验

@Transactional(rollbackFor = Exception.class)
public void test(){
    User user = new User();
    user.setId(123456L).setPassword("123456789");
    userMapper.insert(user);
    try {
        int i = 1/0;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

试验证明,事务没有回滚,尽管出现了异常,数据还是插入进去了

那我们应该如何去解决这个事情呢,即捕获了异常,又会回滚事务

1:在catch中再抛出去
catch (Exception e) {
    e.printStackTrace();
    throw new RuntimeException(e.getMessage());
}

2:手动回滚事务
try {
    int i = 1/0;
} catch (Exception e) {
    e.printStackTrace();
}
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚事务

3.全局异常捕获,事务又将如何呢?

在API中我们通常会设置一个全局异常捕获的类,用于捕获程序员没有手动捕获的未知异常,那这个全局异常是否会影响我们的事务呢,接下来再次试验

// 简单异常处理
@Slf4j
@RestControllerAdvice 
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public APIResponse exceptionHandler(HttpServletRequest req, Exception e) {
        APIResponse<Object> apiResponse = APIResponse.getInstance();
        log.error("出现异常"+e.getMessage());
        e.printStackTrace();
        return apiResponse.failed(e.getMessage());
    }
}

@Transactional(rollbackFor = Exception.class)
public void test() {
    User user = new User();
    user.setId(123456L).setPassword("123456789");
    userMapper.insert(user);
    int i = 1 / 0;
}

试验证明,全局异常捕获不会影响事务的回滚,当程序员手动捕获异常以后不会再进全局异常里面