今天写完Service,想测试一下事务性,看是不是设置的自定义异常都能成功完成数据回滚。
于是我写了一个方法:
@Override
public boolean addNewUser(UserInfo userInfo) {
try{
int count=userMapper.insert(userInfo);
throw new SQLIResultErrorException(dateFormat.format(new Date())+"| 添加用户失败,结果异常!| user name : "+userInfo.getUserName());
}catch (SQLIResultErrorException e){
System.out.println(e.getMessage());
return false;
}
}
结果,当我在测试时调用此方法,方法成功返回false,控制台也输出了异常信息。查看数据库,测试数据依然添加到了数据库里。
然而我已经在类上注解了@Transactional了:
@Transactional(rollbackFor = {Exception.class})
怎么还是没有回滚?
在我请教了一些前辈之后,我才知道**Spring的@Transactional注解只对unchecked类型的异常有效,比如RuntimeException及其子类,对checked异常是不自动回滚的。**简单来说,就是在代码块try…catch中定义的异常Spring事务是不回滚的。
但是,我不想要RuntimeException,那并不符合我的初衷,怎么办?
后来我查阅了一些资料,了解到,虽然Spring对checked异常默认不自动回滚,但是仍然给了一个手动回滚的方法:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
也就是说,在catch里加这样一行代码就可以手动实现异常回滚了。
比如:
@Override
public boolean addNewUser(UserInfo userInfo) {
try{
int count=userMapper.insert(userInfo);
if (count != 1){
throw new SQLIResultErrorException(dateFormat.format(new Date())+"| 添加用户失败,结果异常!| user name : "+userInfo.getUserName());
}
}catch (SQLIResultErrorException e){
System.out.println(e.getMessage());
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
}
return true;
}
这样,当插入数据影响行数错误时,可以检测并回滚,同时可以正常返回,告诉调用类插入未成功且已经回滚。