Spring事务传播机制-操作版

大家好,Spring事务传播机制大家应该都知道,不管是平时的工作还是备战面试,都会被问到,很多时候我们都跟背八股文一样背这个规律,但是却没有实践过,今天我打算用一个实践的操作来跟大家一起温习一下这些事务传播机制。

首先我们知道事务传播机制分为以下几种

事务传播级别含义外层有事务外层无事务备注
REQUIRED 默认事务级别加入外层事务新建一个事务
SUPPORTS支持当前事务加入外层事务以非事务方式运行
MANDATORY强制事务执行加入外层事务报错
REQUIRES_NEW新建一个新事务挂起并新建一个事务新建一个事务新老事务相互独立
NOT_SUPPORTED以非事务方式运行挂起外层事务以非事务方式运行
NEVER以非事务方式运行报错以非事务方式运行
NESTED嵌套事务加入外层事务新建一个事务

外层回滚,内层也要回滚,

内层回滚,外层不用回滚。

接着我以一些实践操作来证实上面的结论。

1、REQUIRED

①  外层没有事务,则新建一个事务

外层代码:

    /**
     * 默认事务,外层没有事务,开启一个新的事务
     * 数据正常保存到数据库
     */
    @Test
    public void save() {
        requiredService.save("chenhuaijie");
    }

内层代码:


    /**
     * 默认配置事务配置
     *
     * @param username
     */
    @Transactional
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果:

 ② 外层有事务,则加入外层事务

外层代码:

 /**
     * 外层事务
     *
     * @param username
     */
    @Transactional
    public void save(String username) {
        requiredService.save(username);
    }

内层代码:

    /**
     * 默认配置事务配置
     *
     * @param username
     */
    @Transactional
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

2、SUPPORTS

① 外层无事务,以非事务方式运行

外层代码

    /**
     * 非事务方式运行
     * 正常保存数据
     *
     * @param username
     */
    public void save(String username) {
        supportsService.save(username);
    }

内层代码

    /**
     * Support事务配置
     *
     * @param username
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果,在service层并没有创建事务

 

② 外层有事务,加入外层事务

外层代码

    /**
     * 以事务方式运行
     * 正常保存数据
     *
     * @param username
     */
    @Transactional
    public void saveWithTransaction(String username) {
        supportsService.save(username);
    }

内层代码

    /**
     * Support事务配置
     *
     * @param username
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

3、MANDATORY

①外层有事务,加入外层事务

外层代码

    /**
     * 加入当前事务
     * 数据保存正常
     *
     * @param username
     */
    @Transactional
    public void saveWithTransaction(String username) {
        mandatoryService.save(username);
    }

内层代码

    /**
     * 外层有事务就跟着外层事务,外层没有事务就报错
     *
     * @param username
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

②外层无事务,报错

外层代码

    /**
     * 报错
     *
     * @param username
     */
    public void save(String username) {
        mandatoryService.save(username);
    }

内层代码

    /**
     * 外层有事务就跟着外层事务,外层没有事务就报错
     *
     * @param username
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

4、REQUIRES_NEW

①外层有事务,挂起外层事务并新建一个事务

外层代码

    /**
     * 存在事务,则新启动一个新的事务
     *
     * @param username
     */
    @Transactional
    public void saveWithTransaction(String username) {
        requiredNewService.save(username);
    }

内层代码

    /**
     * 要求启动一个新的事务
     *
     * @param username
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

②外层无事务,新建一个事务

外层代码

    /**
     * 没有事务,以事务方式运行
     *
     * @param username
     */
    public void save(String username) {
        requiredNewService.save(username);
    }

内层代码

    /**
     * 要求启动一个新的事务
     *
     * @param username
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

5、NOT_SUPPORTED

①:外层有事务,挂起外层事务

外层代码


    @Transactional
    public void saveWithTransaction(String username) {
        notSupportedService.save(username);
    }

内层代码

    /**
     * 如果当前事务存在则挂起当前事务
     *
     * @param username
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

②:外层无事务,以非事务方式运行

外层代码

    public void save(String username) {
        notSupportedService.save("chenhuaijie");
    }

内层代码

    /**
     * 如果当前事务存在则挂起当前事务
     *
     * @param username
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

6、NEVER

①:外层有事务,报错

外层代码

    /**
     * 报错
     *
     * @param username
     */
    @Transactional
    public void saveWithTransaction(String username) {
        neverService.save(username);
    }

内层代码


    /**
     * 外层有事务就跟着外层事务,外层没有事务就报错
     *
     * @param username
     */
    @Transactional(propagation = Propagation.NEVER)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

②:外层无事务,以非事务方式运行

外层代码

    /**
     * 非事务方式运行
     * 数据保存正常
     *
     * @param username
     */
    public void save(String username) {
        neverService.save(username);
    }

内层代码

    /**
     * 外层有事务就跟着外层事务,外层没有事务就报错
     *
     * @param username
     */
    @Transactional(propagation = Propagation.NEVER)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userRepository.save(user);
    }

结果

 

7、NESTED

jpa不支持nested事务传播机制,nested的特点是,

① 外层有事务,加入外层事务,类似于REQUIRED

外层代码

    /**
     * 如果外层有事务,则内层新增一个嵌套事务
     */
    @Transactional(transactionManager = "dataSourceTransactionManager")
    public void saveWithTransaction(String username) {
        nestedService.save(username);
    }

内层代码

    /**
     * 如果当前存在事务则执行一个嵌套事务,如果当前没有事务则新建一个事务
     * 如果外层事务回滚了,内层事务要跟着回滚;如果内层事务回滚了,外层事务不需要回滚
     *
     * @param username
     */
    @Transactional(transactionManager = "dataSourceTransactionManager", propagation = Propagation.NESTED)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userTemplate.save(user);
    }

结果

② 外层无事务,新建一个事务,类似于REQUIRED_NEW

外层代码

    /**
     * 外层没有事务,则内层新建一个事务,此时类似于REQUIRED_NEW
     */
    public void save(String username) {
        nestedService.save(username);
    }

内层代码

    /**
     * 如果当前存在事务则执行一个嵌套事务,如果当前没有事务则新建一个事务
     * 如果外层事务回滚了,内层事务要跟着回滚;如果内层事务回滚了,外层事务不需要回滚
     *
     * @param username
     */
    @Transactional(transactionManager = "dataSourceTransactionManager", propagation = Propagation.NESTED)
    public void save(String username) {
        User user = User.builder().username(username).build();
        userTemplate.save(user);
    }

结果

 

外层回滚带动内层回滚:这种看起来是一个事务的效果

内层回滚不影响外层事务提:这种看起来是独立事务的效果

在一个注解上可以实现两种效果,这也是嵌套事务的巧妙之处。

外层代码:


    /**
     * 实现如下场景:
     * 外事务回滚,内事务也要回滚
     * 但是如果内事务回滚了,外事务不用回滚
     */
    @Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = NullPointerException.class)
    public void save(boolean rollbackOuter, boolean rollbackInner) {
        userTemplate.save(User.builder().username("1").build());

        try {
            nestedService.saveWithNullPointException("2", rollbackInner);
        } catch (Exception e) {

        }

        if (rollbackOuter) {
            throw new NullPointerException();
        }
    }

内层代码:

    @Transactional(transactionManager = "dataSourceTransactionManager", propagation = Propagation.REQUIRES_NEW)
    public void saveWithNullPointException(String username, boolean rollback) {
        User user = User.builder().username(username).build();
        userTemplate.save(user);
        if (rollback) {
            int i = 10 / 0;
        }
    }

测试代码:

    // ====================================================================================================
    // 只有将传播机制设置为NESTED级别,才会同时实现如下两种场景的要求,改成REQUIRED或者REQUIRES_NEW都只能满足其中一种

    /**
     * 内事务回滚,外事务不回滚
     */
    @Test
    public void save1() {
        nestedOuterService.save(false, true);
    }

    /**
     * 外事务回滚,内事务一起回滚
     */
    @Test
    public void save2() {
        nestedOuterService.save(true, false);
    }
    // ====================================================================================================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值