Spring事务的传播机制

1、什么是事务的传播

首先,事务的传播机制是Spring框架实现的功能,是java层面的概念。

事务的传播指的是,一个事务方法A,被另外一个方法B调用的时候,对方法A有何种影响(两个方法事务独立执行、A方法事务合并到B方法事务、或以非事务方式执行等)。

事务的传播机制仅限于不同类方法间相互调用,本文最后阐述。

2、事务的传播机制有哪些

传播机制说明
PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

3、演示事务的传播

对7中传播特性逐一进行演示,为了不增加篇幅,采用伪代码方式演示

1、PROPAGATION_REQUIRED

说明:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。

演示1

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodM() {

	insertTableA();
	methodN();
	insertTableA();

}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodN() {

	insertTableB();
	throw new RuntimeException();
}

结果1

A表、B表均插入失败。
methodM方法存在事务,methodN方法直接加入到methodM方法的事务中,所以methodN抛出异常,methodM方法回滚。

演示2

public void methodM() {

	insertTableA();
	methodN();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodN() {

	insertTableB();
	throw new RuntimeException();
}

结果2

A表插入成功,B表插入失败。
methodM方法不存在事务,methodN方法新建一个事务。
2、PROPAGATION_SUPPORTS

说明:支持当前事务,如果当前没有事务,就以非事务方式执行。

演示

public void methodM() {

	insertTableA();
	methodN();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.SUPPORTS)
public void methodN() {

	insertTableB();
	throw new RuntimeException();
}

结果

A表、B表均插入成功。
methodM方法没有事务,methodN则以非事务的方式运行。
3、PROPAGATION_MANDATORY

说明:使用当前的事务,如果当前没有事务,就抛出异常。

演示

public void methodM() {

	insertTableA();
	methodN();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.MANDATORY)
public void methodN() {

	insertTableB();
}

结果

A表插入成功,B表插入失败。且methodN方法抛出异常。
methodM方法没有事务,methodN运行时则直接抛出异常。
4、PROPAGATION_REQUIRES_NEW

说明:新建事务,如果当前存在事务,把当前事务挂起。

演示

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodM() {

	insertTableA();
	methodN();
	throw new RuntimeException();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRES_NEW)
public void methodN() {

	insertTableB();
}

结果

A表插入失败,B表插入成功。
methodN方法直接新建事务,methodM中抛出异常不影响methodN事务执行。
5、PROPAGATION_NOT_SUPPORTED

说明:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

演示

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodM() {

	insertTableA();
	methodN();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.NOT_SUPPORTED)
public void methodN() {

	insertTableB();
	throw new RuntimeException();
}

结果

A表插入失败,B表插入成功。
methodN方法直接以非事务的方式运行。
6、PROPAGATION_NEVER

说明:以非事务方式执行,如果当前存在事务,则抛出异常。

演示

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodM() {

	insertTableA();
	methodN();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.NEVER)
public void methodN() {

	insertTableB();
}

结果

A表、B表均插入失败。且methodN运行时抛出异常。
methodM方法存在事务,所以methodN运行时抛出异常,导致A表数据也插入不成功。
7、PROPAGATION_NESTED

说明:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

演示

@Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
public void methodM() {

	insertTableA();
	methodN();
}

@Transactional(rollbackFor=Exception.class,propagation= Propagation.NESTED)
public void methodN() {

	insertTableB();
}

结果


4、实现原理

Spring声明式事务的实现原理默认采用动态代理的方式实现,在事务方法的前面动态切入开启事务的代码,在事务方法结束动态切入提交/回滚事务的代码。

事务的传播特性就是根据propagation属性配置的差异,在事务方法被调用时是否需要在本方法中切入 开始|提交|回滚 事务的代码。

5、注意事项

因Spring声明式事务的实现原理为动态代理,所以事务的传播特性仅限于不同类方法间的相互调用,同类中事务方法被调用时,动态代理不生效,所以事务的传播也会失效。可通过上下文的方式注入类自身解决。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值