spring声明式事务回滚
spring 声明式事务
spring声明式事务管理是通过aop实现的,使用时不用修改原有业务代码,只需要通过简单配置追加事务控制功能,同时也最符合非侵入式的理念,因此大多数用户都会选择声明式事务。
默认Spring事务只在发生未被捕获的RuntimeException时才回滚,而发生检查异常是不会回滚的,
checked Exception回滚
1、注解方式
@Transactional(rollbackFor=ClassCastException.class)
2、xml配置方式
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.ClassCastException/>
捕获的RuntimeException回滚
@Transactional public boolean save() { try { // 操作A // 操作B } catch (Exception e) { log.error("事务失败", e); return false; } return Boolean.TRUE;
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)要继续捕获这个异常并处理。
@Transactional
public boolean save() {
try {
// 操作A
// 操作B
} catch (Exception e) {
throw new RuntimeException(message);
return fasle;
}
return Boolean.TRUE;
但是从阿里巴巴的手册上有这么一条,避免直接抛出RuntimeException,应使用有业务含义的自定义异常。并且需要继承 RuntimeException。
throw new UserNotFoundException("user not found"); // 用户不存在
方案2.TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),手动回滚,这样上层就无需去处理异常(推荐)