Spring传播机制(七种)

这篇具有很好参考价值的文章主要介绍了Spring传播机制(七种)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。Propagation枚举则引用了这些类型,开发过程中我们一般直接用Propagation枚举。

1.1 Propagation源码

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);

    private final int value;

    private Propagation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

1.2、类型解析

  • Propagation.REQUIRED(默认机制):如果当前存在事务,那么就加入这个事务,不存在就新建一个事务。
  • Propagation.SUPPORTS:如果当前有事务,加入事务,如果没有则不使用事务
  • Propagation.MANDATORY:使用当前事务,如果当前没有事务,就抛出异常
  • Propagation.REQUIRES_NEW:新建新的事务,如果当前存在事务,就把当前事务挂起
  • Propagation.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,把当前事务挂起
  • Propagation.NEVER:以非事务方式执行操作,如果当前存在事务,就抛出异常
  • Propagation.NESTED:如果当前存在事务,则嵌套在事务内执行。如果当前没有事务,则执行Propagation.REQUIRED类似操作。

1.3 分类举例

参考文档:Spring事务管理中的七种传播机制及示例讲解 | 程序员小羊

传播机制 解释
Propagation.NEVER 非事务执行操作,存在事务,抛出异常
Propagation.MANDATORY 使用当前事务,没有事务,抛出异常

代码案例:

//controller
@RestController
@RequestMapping("/op")
public class TestController {

    @Autowired
    private TestService testService;
    
    @GetMapping("/test1")
    public void test1() {
        testService.test1();
    }
    
}

//service
public interface TestService2 extends BaseService<Test> {

    void test2();

    void test3();
}

@Service
public class TestServiceImpl2 extends BaseServiceImpl<TestMapper, Test> implements TestService2 {


    @Override
    @Transactional(propagation = Propagation.NEVER, rollbackFor = Exception.class)
    public void test2() {
        System.out.println("test2 存在事务 NEVER");
    }

    @Override
    public void test3() {
        System.out.println("test3 没有事务");
    }
}


public interface TestService extends BaseService<Test> {

    int insert(Test test);

    int update(Test test);


    void test1();

    void test4();
}

@Service
public class TestServiceImpl extends BaseServiceImpl<TestMapper, Test> implements TestService {

    @Autowired
    private TestService2 testService2;

    @Override
    public int insert(Test test) {
        return getBaseMapper().insert(test);
    }

    @Override
    public int update(Test test) {
        return getBaseMapper().updateById(test);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void test1() {
        System.out.println("test1 存在事务 REQUIRED");
        //如果在调用NEVER类型的时候,一定要用这种代理的方式,NEVER才会生效
        testService2.test2();
    }

    @Override
    @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
    public void test4() {
        System.out.println("test4 存在事务 MANDATORY");
        testService2.test3();
    }
}

测试结果

Propagation.NEVER

Spring传播机制(七种)

Propagation.MANDATORY

Spring传播机制(七种)

传播机制 解释
Propagation.REQUIRED 需要在事务中执行,外层有事务就加入,没有事务就自己创建一个事务
Propagation.REQUIRES_NEW 需要在一个新的事务中执行,这个事务独立于外层的事务,互不影响

Propagation.REQUIRES_NEW案例

@Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void test5() {
        System.out.println("当前事务 REQUIRED ");
        Test test = new Test();
        test.setUserName("上海");
        test.setAddress("中国");
        getBaseMapper().insert(test);
        //test6用REQUIRES_NEW修饰,里面有异常,那么当前的事务也会回滚,如果test5有异常,test6不会受到影响
        testService2.test6();
        //当前事务进行回滚,test6内容会正常增加
        int i = 1/0;
    }


@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void test6() {
        System.out.println("创建了一个新的事务");
        Test test = new Test();
        test.setUserName("广州");
        test.setAddress("中国");
        getBaseMapper().insert(test);

    }

注意点:

REQUIRES_NEW如果在内层,它里面的事务独立于外层的事务,外层事务如果发送异常回滚跟REQUIRES_NEW里面内容无关,如果REQUIRES_NEW里面内容回滚,那么外层的事务也会跟着回滚。

Propagation.REQUIRES_NEW测试结果

Spring传播机制(七种)

传播机制 解释
Propagation.SUPPORTS 外层有事务就加入,如果没有事务,就以非事务方式执行
Propagation.NOT_SUPPORTED 以非事务的方式执行,执行的时候,先将外层的事务挂起,允许外层有事务。
传播机制 解释
Propagation.NESTED         嵌套事务,它是已经存在事务的真正子事务,嵌套事务开始执行时,会取得一个保存点(savepoint),如果这个嵌套事务失败,将会回滚导这个保存点(savepoint),而不是整个事务的回滚
@Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void test7() {
        System.out.println("当前事务 REQUIRED ");
        Test test = new Test();
        test.setUserName("上海");
        test.setAddress("中国");
        getBaseMapper().insert(test);
        //NESTED事务如果进行回滚,但是不会对它外层的事务造成影响
        try{
            testService2.test8();
        }catch (Exception e){
            
        }
    }

  @Override
    @Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
    public void test8() {
        System.out.println("创建了一个新的子事务");
        Test test = new Test();
        test.setUserName("广州");
        test.setAddress("中国");
        getBaseMapper().insert(test);
        int i = 1/0;
    }

二、总结

2.1 REQUIRED,REQUIRES_NEW,NESTED

状态 REQUIRES_NEW(两个独立事务) NESTED(B事务嵌套在A事务中) REQUIRED同一个事务
A异常B正常 A回滚,B正常提交 A与B一起回滚 A与B一起回滚
A正常B异常 B先回滚,A正常提交 B先回滚,A再正常提交 A与B一起回滚
A正常B正常 B先提交,A再提交 A与B一起提交 A与B一起提交

2.2 三者不同

参考文档:Spring嵌套事务异常Transaction rolled back because it has been marked as rollback-only_spring事务嵌套异常处理_Black·Tea的博客-CSDN博客

REQUIRED

  • 假设在A⽅法存在⼀个当前事务,B⽅法的事务传播机制为REQUIRED,则B⽅法会合并到A⽅法的事务⾥执⾏。
  • A、B任意⼀个⽅法异常(默认是RuntimeException和Error)都会导致A、B的操作被回滚。
  • Spring事务管理器不会吞异常。
  • B异常后会抛给A,A如果没有catch这个异常,会继续向上抛。如果A catch住了,Spring事务管理器会替A向上抛⼀个
  • UnexpectedRollbackException。总之,⼀旦A、B回滚,A的调⽤⽅⼀定能收到⼀个异常感知到回滚。(问题所在)

REQUIRES_NEW

  • 如果B发⽣异常,B事务⼀定回滚,B的异常随后会抛给A,如果A catch住了这个异常,A不会回滚,否则A也会回滚。
  • 如果A发⽣异常,则只会回滚A,不会回滚B。

NESTED文章来源地址https://www.toymoban.com/news/detail-455242.html

  • 如果B异常,B⼀定回滚,B的异常随后会抛给A,如果A catch住了这个异常,A不会回滚,否则A也会回滚。这种情况和REQUIRES_NEW⼀样。
  • 如果A发⽣异常,则A、B都会回滚。

2.3 手动回滚

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void test7() {
        System.out.println("当前事务 REQUIRED ");
        Test test = new Test();
        test.setUserName("上海");
        test.setAddress("中国");
        getBaseMapper().insert(test);
        //NESTED事务如果进行回滚,但是不会对它外层的事务造成影响
        try{
            testService2.test8();
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

到了这里,关于Spring传播机制(七种)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring 事务和事务传播机制

    目录 🐇今日良言:生命只有一次,你要活的畅快淋漓 🐇一、Sping 事务 1.Spring 中事务的实现 2.Spring 中事务隔离级别 🐇二、Spring 事务传播机制 1.基本概念 2.详细介绍 1.Spring 中事务的实现 在MySQL中也有事务,如下链接是博主之前写的关于MySQL事务的博客: 如何理解数据库事务

    2024年02月07日
    浏览(29)
  • 【Spring】深入理解 Spring 事务及其传播机制

    在 Spring 框架中,事务(Transaction)是一种用于管理数据库操作的机制,旨在 确保数据的 一致性、可靠性和完整性 。事务可以将一组数据库操作(如插入、更新、删除等)视为一个单独的执行单元,要么 全部成功地执行,要么全部回滚 。这样可以确保数据库在任何时候都保

    2024年02月12日
    浏览(51)
  • Spring事务的四大特性+事务的传播机制+隔离机制

    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 事务是一个原子操作, 由一系列动作组成。 组成一个事务的多个数据库操作是一个不可分割的原子单元 ,只有所有的操作执行成功,整个事务才提交。 事务中的任何一个数据库操作失败

    2024年01月20日
    浏览(32)
  • Spring事务和事务传播机制(1)

    ❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️ Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客 在Spring框架中,事务管理是一种用于维护数据库操作的一致性和完整性的机制。Spring事务管理提供了灵活的方式来处理事务,包括事务的创建

    2024年02月12日
    浏览(27)
  • Spring—事务及事务的传播机制

    将一组操作封装成一个执行单元, 即这一组操作一同成功 / 一同失败 举个栗子🌰 未使用事务 滑稽老哥给女神转账 520 由于某种原因, 女神并未收到转账的 520, 而滑稽老哥却被扣款 520 使用事务 滑稽老哥给女神转账 520 由于某种原因, 女神并未收到转账的 520 因为使用事务, 所以

    2024年02月13日
    浏览(37)
  • Spring事务传播的7种机制

    1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果 当前没有事务,则创建一个新的事务。 2. Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的 方式继续运行。 3. Propagation.MANDATORY:(mandatory:强制

    2024年02月09日
    浏览(32)
  • Spring @Transactional事务传播机制详解

    我们日常工作中极少使用事务传播级别,单纯只是使用事务和rollbackfor抛出异常来解决事务问题,但其实我们很多时候使用的是不正确的,或者说会造成事务粒度过大,本文详解一下事务传播级别,也让自己更好地处理事务问题。 1.什么是事务传播机制? 举个栗子,方法A是一

    2024年02月14日
    浏览(32)
  • Spring Boot 事务和事务传播机制

    事务定义 将一组操作封装成一个执行单元 (封装到一起),这一组的执行具备原子性, 那么就要么全部成功,要么全部失败. 为什么要用事务? 比如转账分为两个操作: 第一步操作:A 账户-100 元。 第二步操作:B账户 +100 元。 如果没有事务,第一步执行成功了,第二步执行失败了,

    2024年02月11日
    浏览(29)
  • 【JavaEE进阶】Spring事务和事务传播机制

    Spring 事务是 Spring 框架提供的一种机制,用于 管理数据库操作或其他资源的一组相关操作 ,以确保它们在一个原子、一致、可靠和隔离的执行单元内进行。事务用于维护数据的完整性并支持并发访问数据库时的数据一致性。 Spring 事务的主要特点包括: 原子性(Atomicity):

    2024年02月09日
    浏览(54)
  • spring-transaction源码分析(1)概述和事务传播级别

    spring-tx包使用注解驱动和AOP通知将事务开启、提交/回滚、以及复杂的传播机制封装了起来,开发者不再需要编写事务管理的代码,而是可以只关注自己的业务逻辑。 本文将简单介绍spring-tx使用步骤以及七种事务传播级别。 后续文章会阅读源码,深入分析spring-tx aop通知、七种

    2024年02月03日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包