事务的七种传播机制
@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
如果当前存在事务,则以嵌套方式执行
什么叫嵌套呢
- 主事务和嵌套事务属于同一个事务
- 嵌套事务出错回滚不会影响主事务
- 主事务回滚会将嵌套事务一起回滚了