最近在开发中遇到了一种很奇怪的现象,在一个service中开启事务并且做两次insert,当程序走到第二个insert时抛出Exception异常,service走完后,第一个insert插入到了数据库。
@Transactional
public void service (){
insert();
insert();
}
针对这个问题,查找了一些原因,发现Spring在做事务回滚时捕获的是RuntimeException运行时异常,而我的insert抛出的是Exception,所以导致事务失效。
以前的写法
public void insert(){
try {
//...
} catch (Exception e) {
throw new Exception(e);
}
}
现在的写法
public void insert(){
try {
//...
} catch (RuntimeException e) {
throw new RuntimeException(e);
}
}
Spring在操作事务时,必须抛出运行时异常,事务才有效。
后来,我又发现了第二种事务回滚的方法,个人认为这种方案比上面的灵活一些。
@Transactional
public void service (){
try {
//...
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
这种方案不用必须抛出运行时异常,Exception异常即可,重点是使用
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
进行事务回滚。