spring 事务传播

spring事务传播有如下7种:
[1] 死活不要事务的
Propagation.NEVER:没有就非事务执行,有就抛出异常
Propagation.NOT_SUPPORTED:没有就非事务执行,有就直接挂起当前事务,然后非事务执行

[2] 可有可无的
Propagation.SUPPORTS:有就用,没有就算了

[3] 必须有事务的
Propagation.REQUIRES_NEW:有没有都新建事务,如果原来有事务,将原来的挂起
Propagation.NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务
Propagation.REQUIRED:如果没有,就新建一个事务;如果有,就加入当前事务
Propagation.MANDATORY:如果没有,就抛出异常;如果有,就加入当前事务

下面代码演示:

//通用方法
/**
     * 查找name的账户
     * @author lsw
     * @date 2022/5/26 11:16
     */
    public Account getByName(String name){
        Wrapper<Account> wrapper = new EntityWrapper<>();
        wrapper.eq("name", name);
        return this.accountMapper.selectList(wrapper).get(0);
    }
1.Propagation.NEVER

1)NEVER不支持事务的情况

//下面是AccountServiceImpl.java 转出与转入的方法
/**
     * 转出,张三余额-100
     * @author lsw
     * @date 2022/5/26 11:12
     */
    @Transactional
    public void test_never1(){
        Account account = this.getByName("张三");
        account.setBalance(account.getBalance() - 100d);
        this.accountMapper.updateById(account);

        try{
            //注意,这里要用accountService来调用test_never2,不然事务会失效。
            //这和aop的原理有关系;如果直接this调用的话,就不是用代理对象调用的了,就不会有事务。
            accountService.test_never2();
        }catch(Exception e){
            e.printStackTrace();
        }

        int x = 10;
        if(x == 10){
            throw new NullPointerException("出错啦");
        }
    }

    /**
     * 转入,李四余额+100
     * @author lsw
     * @date 2022/5/26 11:12
     */
    @Transactional(propagation = Propagation.NEVER)
    public void test_never2(){
        Account account = this.getByName("李四");
        account.setBalance(account.getBalance() + 100d);
        this.accountMapper.updateById(account);
        int x = 10;
        if(x == 10){
            throw new NullPointerException("出错啦");
        }
    }
//如果的情况,启动工程会直接报错,因为调用never的地方,不能有事务

2)NEVER事务回滚情况


客户账户余额

将test_never1方法的事务注释掉,此时工程可以正常启动。test_never1和test_never2都
没有事务。
执行accountService.test_never1,两个方法都报错,因为没有事务,所以数据不会回滚

AccountServiceImpl.java
/**
     * 转出,张三余额-100
     * @author lsw
     * @date 2022/5/26 11:12
     */
    //@Transactional
    public void test_never1(){
        Account account = this.getByName("张三");
        account.setBalance(account.getBalance() - 100d);
        this.accountMapper.updateById(account);

        try{
            //注意,这里要用accountService来调用test_never2,不然事务会失效。
            //这和aop的原理有关系;如果直接this调用的话,就不是用代理对象调用的了,就不会有事务。
            accountService.test_never2();
        }catch(Exception e){
            e.printStackTrace();
        }

        int x = 10;
        if(x == 10){
            throw new NullPointerException("出错啦");
        }
    }

    /**
     * 转入,李四余额+100
     * @author lsw
     * @date 2022/5/26 11:12
     */
    @Transactional(propagation = Propagation.NEVER)
    public void test_never2(){
        Account account = this.getByName("李四");
        account.setBalance(account.getBalance() + 100d);
        this.accountMapper.updateById(account);
        int x = 10;
        if(x == 10){
            throw new NullPointerException("出错啦");
        }
    }
Test.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {

    @Autowired
    AccountServiceImpl accountService;

    @org.junit.Test
    public void test(){
        accountService.test_never1();
    }
}
执行结果

在上面的执行结果可以看出,张三账户少了100,李四账户多了100,事务没有回滚

2.Propagation.NOT_SUPPORTED

将数据还原,如下:


客户账户余额

1)not_supported调用方存在事务的情况

/**
     * 转出,张三余额-100
     * @author lsw
     * @date 2022/5/26 11:12
     */
    @Transactional
    public void test_not_supported1(){
        Account account = this.getByName("张三");
        account.setBalance(account.getBalance() - 100d);
        this.accountMapper.updateById(account);

        //注意,这里要用accountService来调用当前service其他方法,不然事务会失效。
        //这和aop的原理有关系;如果直接this调用的话,就不是用代理对象调用的了,就不会有事务。
        accountService.test_not_supported2();
    }

    /**
     * 转入,李四余额+100
     * @author lsw
     * @date 2022/5/26 11:12
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void test_not_supported2(){
        Account account = this.getByName("李四");
        account.setBalance(account.getBalance() + 100d);
        this.accountMapper.updateById(account);
        int x = 10;
        if(x == 10){
            throw new RuntimeException("出错啦");
        }
    }
@org.junit.Test
    public void test_not_supported(){
        accountService.test_not_supported1();
    }

执行完test_not_supported之后,test_not_supported1中由于异常传递报错 事务回滚,test_not_supported2中因为没有事务,就算报错,事务也不会回滚。


账户情况

2)not_supported调用方不存在事务的情况
数据还原


客户账户余额

代码就不在这里贴了,相比1)中,就是把 test_not_supported1的Transational注释掉


客户账户余额

由此看出,如果调用方不存在事务,test_not_supported1和test_not_supported2都
不会回滚。参考not_supported的传播特性。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容