Spring 事务管理 事务的传播级别

例子:对于默认的传播级别 REQUIRED 的测试

首先对于 REQUIRED 的解释如下: 默认事务类型,如果没有,就新建一个事务;如果有,就加入当前事务,也就是大家都使用同一个事务模型,只要有一个发生了异常,那么整个事务都会回滚。

其中对于发生异常导致事务回滚需要注重理解,否则对于REQUIRES_NEW 就会认为某些行为与预先的不一样。

下面针对 REQUIRES_NEW  的测试如下:

@Service
public class A {

    @Resource
    private PersonMapper personMapper;

    @Resource
    private B b;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void save() {
        personMapper.insert(Person.builder().name("A").age(12).build());
        b.save();
    }
}
@Service
public class B {

    @Resource
    private PersonMapper personMapper;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void save() {
        personMapper.insert(Person.builder().name("B").age(12).build());
        throw new RuntimeException();
    }
}

    @GetMapping(value = "/get2")
    public Object get2() {
        a.save();
        return "success";
    }

由于最开始对于异常回滚理解错误,认为在调用A的save()方法时,创建一个事务,这时再在 调用 b的save() 由于传播级别是创建新的事务,所以B抛出异常,应该仅仅会导致B的保存失败,但是实际测试却发现,A,B的保存都失败了,经过仔细的思考,认为,事务重新创建应该是没有问题的,可能是对于异常回滚的理解错误导致的。

于是修改了A 如下:

@Service
public class A {

    @Resource
    private PersonMapper personMapper;

    @Resource
    private B b;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void save() {
        personMapper.insert(Person.builder().name("A").age(12).build());
        try{
            b.save();
        }catch (Exception e){

        }
    }
}

经过测试,发现此时就是 B保存失败而A保存成功了,经过测试推论如下:

在A对象中没有追加try catch的时候,当B 抛出异常的时候,B的事务回滚,但是由于并没有对该异常进行处理,于是该异常扩散到了A中的调用点(b.save();)由于此处的异常,因而导致A回滚了,当追加 try catch 之后 此异常就不会导致A回滚了。


为了验证此猜想,编写如下测试用例:

@Service
public class A {

    @Resource
    private PersonMapper personMapper;

    @Resource
    private B b;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void save() {
        personMapper.insert(Person.builder().name("A").age(12).build());
        try{
            b.save();
        }catch (Exception e){

        }
    }
}
@Service
public class B {

    @Resource
    private PersonMapper personMapper;


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void save() {
        personMapper.insert(Person.builder().name("B").age(12).build());
        throw new RuntimeException();
    }
}
在进行测试,就发现事务回滚了,表明B中的异常导致了整个事务的回滚。

下面继续测试嵌套事务 NESTED :嵌套事务 类似于后一个事务为第一个事务的子事务

经过测试规则如下:父事务回滚,子事务一定回滚,但是子事务回滚,不影响父事务回滚。

   PROPAGATION_SUPPORTS:如果没有,就以非事务方式执行;如果有,就使用当前事务。


以下的事务就比较容易理解了:


    PROPAGATION_NOT_SUPPORTED:如果没有,就以非事务方式执行;如果有,就将当前事务挂起。即无论如何不支持事务。

    PROPAGATION_NEVER:如果没有,就以非事务方式执行;如果有,就抛出异常。

    PROPAGATION_MANDATORY:如果没有,就抛出异常;如果有,就使用当前事务。









阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页