首页 > 技术文章 > spring声明式事务回滚

magic101 2019-04-10 16:08 原文

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(),手动回滚,这样上层就无需去处理异常(推荐)

 

推荐阅读