`
heroliuxun
  • 浏览: 23835 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring 声明式事务中try catch捕获异常

阅读更多
最近遇到这样的问题,使用spring时,在业务层需要捕获异常(特殊需要),当前一般情况下不需要这样做的。具体如下:
在ServiceA类中有method1,在该方法中调用另一个ServiceB类的method2方法时(假定该方法抛出异常),method1方法捕获该异常但是没有向上抛出。spring提示:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

以下是ServiceA的示例代码
@Transactional(rollbackFor = Throwable.class)//默认事务传播方式required
public Class ServiceA {
   
    @Autowired 
    private Dao dao;

    @Autowired 
    private ServiceB serviceB;  // 注入另一Service Bean
   
    public void method1() {

        dao.insert(vo);  // 保存ServiceA的vo对象
        try {
            serviceB.method2(vo); // 保存ServiceB的vo对象
        } catch (CustomException e) {
            // 捕获自定义异常,但是没有向上抛出
        }

    }
}


以下是ServiceB的示例代码
@Transactional(rollbackFor = Throwable.class)//默认事务传播方式required
public Class ServiceB {
   
    @Autowired 
    private Dao dao;
   
    public void method2() throws CustomException {

        dao.insert(vo);  // 保存ServiceA的vo对象
    }
}

出现以上原因是spring执行method1方法时,开启一个新的事物,当调用method2方法时,当method2方法加入到method1方法的当前事务,当method2抛出异常,spring标记事务为回滚状态,method1方法捕获该异常,但没有抛出,spring会提交method1的事务,但spring发现该事务已经标记为回滚状态,而代码中却要提交事务,所以才会抛出以上的异常。


解决的方法:在ServiceB的method2方法上注解,告诉spring当该方法抛出自定义异常CustomException时,不要回滚事务,这样当该方法抛出异常时,spring不会标记事务为回滚状态。
@Transactional(noRollbackFor=CustomException.class)
public void method2() throws CustomException{
}
  • 大小: 6.5 KB
分享到:
评论
2 楼 雪山肥大象 2018-04-19  
奇怪的是,如果把 serviceB.method2(vo)这method2方法放到ServiceA中,就不会报这个异常:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
1 楼 穿围裙的程序员 2015-04-27  
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public void testC() throws Exception{
Random random = new Random();
dmo.update("insert into chh_test(id,name,code) values(?,?,?)",random.nextInt(5),"ccc",random.nextInt());
int i = 2/0;
}


public void testD() throws Exception{
testC();
}

@Test
public void testE(){
try {
testD();
} catch (Exception e) {
e.printStackTrace();
}
}

在用Junit运行方法 testE() 也不回滚是怎么回事?

我把Transactional加在了testC(),不是应该在 testC()抛异常的时候就回滚么?

相关推荐

Global site tag (gtag.js) - Google Analytics