springboot中实现本地事务很简单:
1.启动类中开启事务支持的注解 @EnableTransactionManagement
2.在需要事务的方法上加@Transactional注解
//会在此处写几段代码进行比较说明
//1.抛出一个Exception
//结果是不会回滚
@Transactional
public void test1(User user) throws Exception{
userService.add(user);
throw new Exception("抛出异常");
}
//2.抛出一个RuntimeException//结果是回滚
@Transactional
public void test2(User user) throws Exception{
userService.add(user);
throw new RuntimeException("抛出异常");
}
//3.抛出一个Exception,注解@Transactional(rollbackFor=Exception.class)
//结果是回滚
@Transactional(rollbackFor=Exception.class)
public void test1(User user) throws Exception{
userService.add(user);
throw new Exception("抛出异常");
}
结论一:事务默认回滚的是unchecked异常,如RuntimeException; 不会处理checked异常,如Exception
解决办法:注解@Transactional上添加说明回滚的异常,如rollbackFor=Exception.class
//4.使用try catch捕获异常,但catch内不抛出
//结果是不会回滚
@Transactional(rollbackFor=Exception.class)
public void test1(User user) throws Exception{
try{
userService.add(user);
throw new Exception("抛出异常");
}catch(Exception e){
e.printStackTrace();
}
}
//5.使用try catch捕获异常,catch内抛出
//结果是回滚
@Transactional(rollbackFor=Exception.class)
public void test1(User user) throws Exception{
try{
userService.add(user);
throw new Exception("抛出异常");
}catch(Exception e){
e.printStackTrace();
throw e;
}
}
结论二: try catch捕获到try中出现的异常,会在catch内进行处理, 但需要在catch中主动将该异常抛出,否则事务无法捕获到该异常进行回滚(可以理解为try catch捕获异常会将该异常吃了,想要再让事务发现该异常,需要catch中主动抛出)
解决办法: catch(Exception e){throw e}.
//6.try catch捕获异常,不抛出,进行手动回滚,不指定回滚异常类型
//结果是回滚
@Transactional
public void test1(User user) {
try{
userService.add(user);
throw new Exception("抛出异常");
}catch(Exception e){
TransactionAspecSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
}
//7.try catch捕获异常,不抛出,进行手动回滚,指定回滚异常类型
//结果是回滚
@Transactional(rollbackFor=Exception.class)
public void test1(User user) {
try{
userService.add(user);
throw new Exception("抛出异常");
}catch(Exception e){
TransactionAspecSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
}
结论三:不抛出异常,可直接在try catch内进行处理, 手动回滚事务
解决办法:catch内添加TransactionAspecSupport.currentTransactionStatus().setRollbackOnly();
并且因为没有抛出异常,可不指定rollbackfor
注意: (1)事务控制只能是public方法 (2)本地事务控制的方法,在执行完所有结果之前是没有提交的,但是在抛出异常之前执行过的操作(如insert),会占用数据库的主键id