Spring事务try catch后还发生了回滚

Spring事务的7种传播行为

1.REQUIRED(默认): 如果当前没有事务,就创建事务;如果当前存在事务,就加入该事务.
2.REQUIRES_NEW: 新建事务,如果当前存在事务,则把当前事务挂起,这个方法会独立提交事务,不受外部事务的影响,同时自身异常也不会影响外部事务.
3.SUPPORTS: 如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务方式运行.
4.NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起.
5.MANDATORY: 如果当前存在事务,就加入该事务;当前没有事务,则抛出异常,即外部方法必须有事务(学个单词:mandatory-强制性的;强制的;法定的;义务的).
6.NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常,即外部方法必须无事务.
7.NESTED: 如果当前存在事务,则它成为外部事务的一个内嵌事务,只有等外部事务提交才能提交;如果当前没有事务,则该取值等价于REQUIRED

记一种try catch之后还发生回滚的情况

	@Override
    @Transactional(rollbackFor = Exception.class)
    public void transactionA() {
        try {
            T t = new T();
            t.setK(11);
            this.baseMapper.insert(t);
            TransactionBService.transactionB();//TransactionBService通过Spring容器注入
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transactionB() {
        T t = new T();
        t.setK(22);
        this.baseMapper.insert(t);
        throw new RuntimeException("error");
    }

A方法和B方法,都标记了@Transactional(rollbackFor = Exception.class),在A方法中调用了B方法,B方法报错,A方法和B方法都进行了回滚,没有插入数据库.
原因分析: 首先我们要知道,外部经过Spring容器调用service的方法,事务才会生效,service类内部互相调用方法事务是不会生效的,Spring事务的实现基础是AOP, 而AOP的原理是动态代理,若是类自身的调用,而不是代理对象去调用,就不会产生AOP,这样Spring就不能把你的代码织入到约定的流程中去.
接着讲上面这个问题,A方法调用B方法,会在B方法的时候启动代理,然后再去执行B的方法.代理发现当前存在事务,且B方法的传播行为为Propagation.REQUIRED,方法的传播行为为Propagation.REQUIRED,就会把B的事务并入到当前事务中.当B方法抛出异常,就已经把A方法的事务(当前事务)标记为回滚,然后抛出异常;这个时候A方法try catch捕获异常,但事务已经是回滚状态了.

@Transactional(rollbackFor = Exception.class)

Exception分为运行时异常RuntimeException和非运行时异常.当@Transactional注解作用于类上时,该类的所有public方法都将具有将传播类型的事务,我们也可以把该注解在方法上,这样不同方法就可以指定各自的事务传播类型.
@Transactional 注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚.

额外基础小知识:
运行时异常是指RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理.这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生.
非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类.如IOException、SQLException等以及用户自定义的Exception异常.对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值