背景知识:默认spring事务只在发生未被捕获的 runtimeExcetpion时才回滚。spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeException的异常。下面代码中,我们通过自定义的try-catch代码块将数据库操作过程中发生的异常进行了手动捕获处理,所以方法不在抛出异常,spring事务管理的aop自然也无法捕获进行事务回滚。
if(needToSave){
try {
userDao.save(user);
userCapabilityQuotaDao.save(capabilityQuota);
} catch (Exception e) {
logger.info("业务执行异常,异常信息:"+e);
}
}
解决方案:
方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理,但是这种方法存在一个缺陷,无法return一些提示信息给前端,用户友好度不高。
方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常,此处在手工进行事务回滚后,依旧可以正常返回提示信息给前端,对用户进行提醒,比较贴合实际。