事务的七种传播机制

@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})

测试类

为什么测试的时候每个方法都要分成不同的类是同类调用会让事务失效

REQUIRED

如果当前没有事务,就创建一个新事务,如果当前存在事务就加入该事务

实例

@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);
        }
    }
​
}

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

结果

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

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

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事务都回滚

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事务都回滚

SUPPORTS

支持当前事务,如果当前没有事务就以非事务方式运行

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事务都不会滚

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事务都回滚

MANDATORY

支持当前事务,如果不存在事务,则抛出异常

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异常

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事务都回滚

REQUIRES_NEW

如果有事务存在,挂起当前事务,并创建一个新事物

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事务回滚

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 这种情况,外层的事务不会影响内层的事务,但内层事务的异常是会影响到外层事务

NOT_SUPPORTED

以非事务方式运行,如果有事务存在,挂起当前事务

A方法无事物,B方法加入事务

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事务都不回滚

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方法,一个有事务,一个没事务

NEVER

以非事务方式运行,如果有事务则抛出异常

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'"

NESTED

如果当前存在事务,则以嵌套方式执行

什么叫嵌套呢

  1. 主事务和嵌套事务属于同一个事务
  2. 嵌套事务出错回滚不会影响主事务
  3. 主事务回滚会将嵌套事务一起回滚了

转载自码农晴明_的博客-CSDN博客_spring传播机制

Last modification:January 11, 2023
如果觉得我的文章对你有用,请随意赞赏