Spring事务的7种传播机制实例代码及分析

spring定义了7种事务传播机制

REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED)

SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS)

MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY)

REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW)

NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)

NEVER(TransactionDefinition.PROPAGATION_NEVER)

NESTED(TransactionDefinition.PROPAGATION_NESTED)

 
下面会根据上面其中传播行为进行实际代码测试:

 
测试前准备 :
 

实体类

@Data
public class TransactionalUser {
    private String userName;


    private String userNo;


    private Integer id;


    private Integer age;


    public TransactionalUser() {
    }


    public TransactionalUser(String userName, String userNo, Integer age) {
        this.userName = userName;
        this.userNo = userNo;
        this.age = age;
    }
}

Mapper

insert into transactional_test(user_name,user_no,age) values (#{userName},#{userNo},#{age})

测试类

注 : 这里为什么测试的每个方法都要分成不同类;主要是因为同类调用会致使事务失效;

@Service
public class TransactionalTest {

    @Autowired
    private A methodA;

    @Autowired
    private B methodB;

    @Autowired
    private PurchaseMapper purchaseMapper;

    public void send() {
        methodA.testA();
    }

    @Service
    class A {
        public void testA() {
            TransactionalUser user = new TransactionalUser("A","123",1);
            // A方法添加数据
            purchaseMapper.transactionalInsert(user);
            methodB.testB();
        }

    }

    @Service
    class B {
        @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testB() {
            TransactionalUser user = new TransactionalUser("B","321",2);
            // B方法添加数据
            purchaseMapper.transactionalInsert(user);
        }
    }

}

1、Propagation.REQUIRED : @Transactional 注解默认属性;如果当前存在事务就加入该事务,如果当前没有事务就新建一个事务。

示例1: A方法不加事务,B方法加入事务;

@Service
class A {
    public void testA() {
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
       // int i = 5/0;
    }
}


@Service
class B {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法加入异常,A、B事务都不回滚。
B方法加入异常,A事务不回滚,B事务回滚。

 

示例2 : A方法加事务B方法不加事务

@Service
class A {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }
}


@Service
class B {
    public void testB() {
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法加入异常,A、B事务都回滚
B方法加入异常,A、B事务都回滚。

 

示例3 : A方法加事务B方法加事务

@Service
class A {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }


}

@Service
class B {
      // B的事务会加入到A中
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法加入异常,A、B事务都回滚
B方法加入异常,A、B事务都回滚
 

===================================== 分隔线 =====================================
 
2、Propagation.SUPPORTS : 支持当前事务,如果当前没有事务,就以非事务方式运行

示例1 : A方法没有事务,B方法加入事务

@Service
class A {
   // @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5/0;
    }

}


@Service
class B {
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法加入异常,A、B事务都不回滚
B方法加入异常,A、B事务都不回滚
 

示例2 : A方法加入事务,B方法加入事务

@Service
class A {
       @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }


}

@Service
class B {
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法加入异常,A、B事务都回滚
B方法加入异常,A、B事务都回滚
 

===================================== 分隔线 =====================================
 

3、Propagation.MANDATORY : 支持当前事务,如果不存在事务,则抛出异常

示例1: A方法不加事务,B方法加入事务

@Service
class A {
       //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }
}


@Service
class B {
    @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常不会回滚,B方法不执行,并抛出 " No existing transaction found for transaction marked with propagation ‘mandatory’" 异常

 

示例2 : A方法加事务,B方法加事务

@Service
class A {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }

}

@Service
class B {
    @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A、B事务都回滚
B方法异常,A、B事务都回滚
 

===================================== 分隔线 =====================================
 

4、Propagation.REQUIRES_NEW : 如果有事务存在,挂起当前事务,并创建一个新的事务

示例1: A方法不加事务,B方法加入事务

@Service
class A {
    //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }
}

@Service
class B {
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A、B事务都不回滚
B方法异常,A事务不回滚、B事务回滚
 

示例2 : A方法加入事务,B方法加入事务

@Service
class A {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }


}

@Service
class B {
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A事务回滚,B事务不回滚
B方法异常,A、B事务都回滚
 
这里总结一下,REQUIRES_NEW的这种情况,外层事物的异常不会影响内层事务,但内层事务的异常是会影响到外层事务。

 

===================================== 分隔线 =====================================
 

5、Propagation.NOT_SUPPORTED : 以非事务方式运行,如果有事务存在,挂起当前事务。

示例1 : A方法无事务,B方法加入事务

@Service
class A {
    //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }

}

@Service
class B {
    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A、B事务都不回滚
B方法异常,A、B事务都不回滚
 

示例2 : A方法加入事务,B方法加入事务

@Service
class A {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }

}

@Service
class B {
    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法异常,A事务回滚、B事务不回滚
B方法异常,A事务回滚、B事务不回滚
 

总结一下,这里A方法异常时,看似和"REQUIRES_NEW"很像,都是挂起了A事务,这样A和B两个方法就完全互不影响了,区别在于B方法,一个有事务,一个没事务。

 

===================================== 分隔线 =====================================
 

6、Propagation.NEVER : 以非事务方式运行,如果有事务则抛出异常

示例1: A方法开启事务,B方法开启事务

@Service
class A {
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }
}

@Service
class B {
    @Transactional(propagation = Propagation.NEVER, rollbackFor = Exception.class)
    public void testB() {
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A、B数据都没成功添加,并抛出异常 "Existing transaction found for transaction marked with propagation 'never'"

 

===================================== 分隔线=====================================
 
7、Propagation.NESTED : 如果当前存在事务,则以嵌套方式执行

在做这种方式的传播行为的测试时,思考了很久,因为不太清楚"嵌套"到底是什么概念,以及和其它传播行为的区别是什么?搜索了资料 参考了 这篇博客

https://www.jianshu.com/p/c6d4095f5833

总结一下Propagation.NESTED,就是上面那篇博客中最后提到的

  • 主事务和嵌套事务属于同一个事务

  • 嵌套事务出错回滚不会影响到主事务

  • 主事务回滚会将嵌套事务一起回滚了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值