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 : 如果当前存在事务,则以嵌套方式执行
在做这种方式的传播行为的测试时,思考了很久,因为不太清楚"嵌套"到底是什么概念,以及和其它传播行为的区别是什么?搜索了资料 参考了 这篇博客
总结一下Propagation.NESTED,就是上面那篇博客中最后提到的
-
主事务和嵌套事务属于同一个事务
-
嵌套事务出错回滚不会影响到主事务
-
主事务回滚会将嵌套事务一起回滚了