spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)

@transactional注解,默认啥都不指定的时候,我们使用的就是PROPAGATION_REQUIRED这种方式。

PROPAGATION_REQUIRED:业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务。这是spring默认的传播行为。

翻译一下就是:看一下调用我的上层方法有没有事务,有的话,就舍弃我的事务,加入上层方法的事务中去.

往往很多小伙伴在使用声明式事物的时候,大部分使用的就是这种默认的传播方式,就顶多加上一个异常指定@Transactional(rollbackFor = Exception.class)

试验一:一个方法调另两个方法,这个方法没加@transactional,那两个方法上都加了@transactional,那么创建了几个sqlsession,共有几个事务

试验得知,bb()方法一个sqlsession,一个事务.cc()方法一个sqlsession,一个事务.

一共两个sqlsession,  一个sqlsession对应一个事务,一共两个事务.

先创建一个sqlsession执行完后就把它关闭,

然后第二个sqlsession再被创建.

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第1张图片

 

试验二:一个方法调另两个方法,这三个方法上都加了@transactional注解,那么创建了几个sqlsession,共有几个事务 

下面这种情况触发了spring事务的默认传播机制REQUIRED,就是如果上层存在事务,那么就舍弃自己的事务,加入上层的事务.

试验得知,下面的情况就是bb()和cc()方法的事务被舍弃了,就只有aa()的事务是生效的.

也就是只剩下aa()方法创建了一个sqlsession,  一个sqlsession对应一个事务,一共一个事务.

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第2张图片

 试验三:feign远程调用的话会对事务的默认传播机制有影响吗

试验得知:feign远程调用会阻挡事务的默认传播.

本来上层方法order服务aa()有事务,user服务aa()方法应该舍弃自己的事务并加入order服务aa()的事务,但是现在由于feign远程调用阻断了事务的传播,导致现在user服务aa()的事务没有舍弃,依然独立存在着.导致现在order服务aa()有个事务,user服务aa()的也有个事务.

order服务的aa()方法创建了一个sqlsession,  一个sqlsession对应一个事务

user服务的aa()方法创建了一个sqlsession,  一个sqlsession对应一个事务

也就是说下面的代码一共创建了2个sqlsession,  2个事务.

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第3张图片

 spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第4张图片

试验四:手动开启事务会对事务的默认传播机制有影响吗 

试验得知:手动开启事务代码并不会影响到事务的默认传播机制.手动开启事务代码和@transactional注解是兼容的.

下面是试验:

手动事务 注入两个bean

@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
TransactionDefinition transactionDefinition;
手动开启事务
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
手动提交事务
dataSourceTransactionManager.commit(transactionStatus);//提交
手动回滚事务
dataSourceTransactionManager.rollback(transactionStatus);//最好是放在catch 里面,防止程序异常而事务一直卡在哪里未提交

上面的这种手动开启事务的方式,也会和直接加@transactional注解的事务的传播效果是一样的吗

开始试验:

情况一:将上层方法aa()改为手动开启事务代码.

运行代码发现,整个过程只创建了一个sqlsession,  一个sqlsession对应一个事务,证明手动开启事务代码并没有对事务的默认传播造成影响.手动开启事务代码和@transactional注解是兼容的.

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第5张图片

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第6张图片

情况二:将下层方法cc()改为手动开启事务代码.

运行代码发现,整个过程只创建了一个sqlsession,  一个sqlsession对应一个事务,证明手动开启事务代码并没有对事务的默认传播造成影响.手动开启事务代码和@transactional注解是兼容的.

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第7张图片

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)_第8张图片

你可能感兴趣的:(事务,java)