1.当我们在谈论嵌套事务的时候,嵌套的是什么?
当看到`嵌套事务`第一反应想到是这样式的:
但这更像PROPAGATION_REQUIRES_NEW
啊,感兴趣可以去打断点执行一下。PROPAGATION_REQUIRES_NEW
事务传播下,方法A调用方法B就是这样,
// 事务A doBegin()
// 事务B doBegin()
// 事务B doCommit()
// 事务A doCommit()
复制代码
而在PROPAGATION_NESTED
事务传播下,打了个断点,会发现只会执行一次doBegin和doCommit:
事务A doBegin()
事务A doCommit()
复制代码
我们用代码输出更加直观。
定义两个方法serviceA和serviceB,使用前者调用后者。前者事务传播使用REQUIRED
,后者使用PROPAGATION_NESTED
。
@Transactional(propagation = Propagation.REQUIRED)
public void serviceA(){
Tcity tcity2 = new Tcity();
tcity2.setId(0);
tcity2.setStateCode("5");
tcity2.setCnCity("测试城市2");
tcity2.setCountryCode("ALB");
tcityMapper.insertSelective(tcity2);
transactionInfo();
test2.serviceB();
}
复制代码
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
public void serviceB() {
Tcity tcity = new Tcity();
tcity.setId(0);
tcity.setStateCode("5");
tcity.setCnCity("测试城市");
tcity.setCountryCode("ALB");
tcityMapper.insertSelective(tcity);
tcityMapper.selectAll2();
transactionInfo();
复制代码
这里的transactionInfo()使用事务同步器管理器TransactionSynchronizationManager
注册一个事务同步器TransactionSynchronization
。
这样在事务完成之后afterCompletion
会输出当前事务是commit
还是rollback
,这样也便于测试,比起去刷新数据库看有没有写入,更加方便快捷直观。
同时使用TransactionSynchronizationManager.getCurrentTransactionName()
可以得到当前事务的名称,这样可以直观的看到当前方法使用的是同一个事务还是不同的事务。
protected void transactionInfo() {
String transactionName = TransactionSynchronizationManager.getCurrentTransactionName();
boolean active = TransactionSynchronizationManager.isActualTransactionActive();
log.info("transactionName:{}, active:{}", transactionName, active);
if (!active) {
log.info("transaction :{} not active", transactionName);
return;
}
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCompletion(int status) {
if (status == STATUS_COMMITTED) {
log.info("transaction :{} co