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;
}
试验证明,全局异常捕获不会影响事务的回滚,当程序员手动捕获异常以后不会再进全局异常里面