@Transactional中的几种事务传播

今天看了一下spring中的几种事务传播,记录一下
源码
一共有7种:(默认:REQUIRED)

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

1.REQUIRED

如果方法在运行的时候存在事务,已经存在了一个事务,那么会加入到该事务中,否则的话自己创建一个新的事务。(spring的默认传播行为就是REQUIRED)

例子:

Food的方法里添加传播行为,User不添加,在调用两者方法的父级方法加上传播行为执行时,因为抛出了异常导致回滚,此时food和user两张表是没有数据入库的,因为food添加了REQUIRED传播行为没有将数据加入到数据库中,user就是加入到了父级的事务中,所以没有数据没有入库。

   @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void add(FoodEntity foodEntity) {
        foodMapper.insert(foodEntity);
    }

    @Override
    public void add(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void contextLoads() {
        FoodEntity foodEntity = new FoodEntity();
        foodEntity.setName("apple");
        foodService.add(foodEntity)

        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.add(usersEntity);
        
        log.info("value={}", 1 / 0);
    }

2.SUPPORTS

如果有事务就在事务的环境下执行,否则反之不在事务的环境下执行。

例子:

如果testSupports方法不加@Transactional(propagation = Propagation.REQUIRED)事务执行,那么addS方法就会将数据存入数据库中;如果加了事务那么就不会将数据存入数据库,因为抛出了异常事务回滚。

	@Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public void addS(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }

	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testSupports() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addS(usersEntity);

        log.info("value={}", 1 / 0);
    }

3.MANDATORY

当前的方法必须在事务中运行,否则的话就抛出异常。

例子:

给子方法添加MANDATORY,主方法不添加事务,此时执行testMandatory方法就会抛出异常,因为addM方法没有在事务中执行。

异常:No existing transaction found for transaction marked with propagation ‘mandatory’

	@Transactional(propagation = Propagation.MANDATORY)
    @Override
    public void addM(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }

	@Test
    public void testMandatory() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addM(usersEntity);
    }

4.REQUIRES_NEW

当前的方法必须在自己的事务内运行,如果有其他的事务就将它挂起。

例子:

在testNew方法中抛出异常并不会造成addNew的事务回滚,因为REQUIRES_NEW会新启一个事务,不受父级的影响。

	@Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void addNew(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }
	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testNew() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addNew(usersEntity);

        log.info("value={}", 1 / 0);
    }

在下面的方法中将异常放在子方法中,对于添加了REQUIRES_NEW传播事务的方法还是不受影响,还是能将数据写入数据库。

	@Override
    public void addNew(FoodEntity foodEntity) {
        log.info("value={}", 1 / 0);
        foodMapper.insert(foodEntity);
    }

	@Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void addNew(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }

	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testNew() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addNew(usersEntity);

        FoodEntity foodEntity = new FoodEntity();
        foodEntity.setName("apple");
        foodService.addNew(foodEntity);
    }

5.NOT_SUPPORTED

当前的方法不会在事务中运行,如果有事务就会将它挂起。

例子:

给addNotSupport方法添加NOT_SUPPORTED,testNotSupport添加REQUIRED运行时,addNotSupport方法还是会将数据添加到数据库中,并没有采取REQUIRED回滚。

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
    @Override
    public void addNotSupport(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }

	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testNotSupport() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addNotSupport(usersEntity);

        log.info("value={}", 1 / 0);
    }

6.NEVER

当前的方法如果在事务中运行,则抛出异常。

例子:

addNever方法在testNever方法中运行会抛出异常,因为testNever方法添加了REQUIRED。

异常:Existing transaction found for transaction marked with propagation ‘never’

	@Transactional(propagation = Propagation.NEVER)
    @Override
    public void addNever(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }

	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testNever() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addM(usersEntity);
    }

7.NESTED

如果存在事务运行,那么这个方法就是在这个事务的嵌套事务内运行,嵌套事务是独立提交或回滚;

如果不存在事务,就按照REQUIRED执行;

如果主事务回滚,子事务一定会回滚;如果子事务回滚,主事务可以回滚,也可以不回滚。

例子:

在主事务中抛出异常,子事务是会跟着一起回滚事务的,这就是NESTED的嵌套事务

	@Transactional(propagation = Propagation.NESTED)
    @Override
    public void addNested(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
    }
	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testNested() {
        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        usersService.addNested(usersEntity);

        log.info("value={}", 1 / 0);
    }

在主事务中try-catch可能出现异常的子事务,那就不会影响其他事务的正常运行。如下方法 food的保存方法就可以正常保存到数据库。

	@Transactional(propagation = Propagation.NESTED)
    @Override
    public void addNested(UsersEntity usersEntity) {
        usersMapper.insert(usersEntity);
        log.info("value={}", 1 / 0);
    }

	@Override
    public void addd(FoodEntity foodEntity) {

        foodMapper.insert(foodEntity);
    }

	@Transactional(propagation = Propagation.REQUIRED)
    @Test
    public void testNested() {

        FoodEntity foodEntity = new FoodEntity();
        foodEntity.setName("apple");
        foodService.addd(foodEntity);


        UsersEntity usersEntity = new UsersEntity();
        usersEntity.setName("小明");
        try {
            // save point
            usersService.addNested(usersEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

事务失效的情况

  1. 方法不是public
  2. 异常类型不是unchecked
  3. 数据库引擎要支持事务,比如mysql的innodb
  4. spring能否扫描到包
  5. 在同一个类不要使用this.XX(方法),因为这个this并不是spring用cglib增强的类,没有被代理,那就没有事务。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值