@Transactional注解的使用以及try-catch捕获异常导致@Transactional注解失效的问题
1、事务管理是应用系统开发中必不可少的一部分。在spring boot 中,使用事务非常简单,只要直接在方法上面加入@Transactional 就可以实现。
2、SpringBoot项目会自动配置一个 DataSourceTransactionManager,所以我们只需在方法(或者类)加上 @Transactional 注解,就自动纳入 Spring 的事务管理了。
如下在方法加上 @Transactional 注解:
@Transactional
public void insertUser() {
User user = new User("张三");
userMapper.insertOneUser(user); //向数据库插入一条记录
throw new RuntimeException("发生异常"); //手动模拟抛出异常
}
抛出异常之后,事务会自动回滚,数据不会插入到数据库。
- 当Transaction内发生unchecked exception的时候,会自动rollback,但是当Transaction内发生checked exception时,是不会自动rollback的。
- 如果使用try-catch捕获异常,则该事务不会回滚。
3、默认spring事务只在发生未被捕获的 RuntimeException 时才回滚。
spring aop异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获RuntimeException的异常,但可以通过配置来捕获特定的异常并回滚。
换句话说在service的方法中不使用try catch或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚。
解决方案:
-
方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理。
-
方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常。
例如
catch (Exception e)
{
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚
result.put("status", 0);
result.put("msg",msg);
return result;
}