Spring 事务的传播属性
事务的传播属性:
1.PROPAGATION_REQUIRED * :如果不存在事务则新建事务,若存在事务则加入事务,默认是这个
2.PROPAGATION_SUPPORTS:若当前没有事务,则已非事务执行
3.PROPAGATION_MANDATORY:若当前没有事务则抛出异常
4.PROPAGATION_REQUIRES_NEW:新建事务,若当前存在事务则挂起。
5.PROPAGATION_NOT_SUPPORTED:已非事务执行,若当前存在事务则挂起。
6.PROPAGATION_NEVER:已非事务执行,若当前存在事务则抛出异常
7.PROPAGATION_NESTED:若当前存在事务则在嵌套事务重执行,若不存在则新建事务
Spring事务
在Spring中,事务是通过AOP来实现的,那么一次完整的事务流程大概是这个样子:
其中除业务代码的其他流程,就是事务对于业务代码的增强。
事务的先决条件
若两个DML语句想要使用同一个事务,必须保证关闭自动提交,并且使用同一个数据库连接。
事务的传播
假设有一个购物车结算服务,用户下单后需要写入订单表,清空购物车,库存-1
// 订单服务
@Transactional(propagation=Propagation.REQUIRED)
public void clearShoppingCart(...) {
// 清空购物车
shoppingCartMapper.clearShoppingCart(...);
// 写入订单表
orderService.purchase(...);
// 减库存
stockService.reduce(...);
}
// OrderService的写入订单
@Transactional(propagation=Propagation.REQUIRED)
public void purchase(...){...}
// stockService的减少库存
@Transactional(propagation=Propagation.REQUIRED)
public void reduce(...){...}
在上面的代码片中,clearShoppingCart事务中又调用了其他两个包含事务的方法,那么在调用时流程图可以理解成(暂不考虑异常):
在代码片中,写入订单以及减少库存的事务属性都是REQUIRED(如果不存在事务则新建事务,若存在事务则加入事务)。所以 “写入订单表开启事务”,“库存减少开启事务” 实际上都是使用的清空购物车的数据库连接。“订单事务提交” 与 “库存减少提交” 可以先理解成什么都没有做。事务的整体提交是由最后的 “清空购物车事务提交” 提交的。
其他事务传播属性
这么一看,其实其他事务属性的大概流程也能推出来,拿REQUIRED_NEW来举例,假设写入订单与减少库存的代码变成如下
// OrderService的写入订单
@Transactional(propagation=Propagation.REQUIRED_NEW)
public void purchase(...){...}
// stockService的减少库存
@Transactional(propagation=Propagation.REQUIRED)
public void reduce(...){...}
那么在 “写入订单开始事务” 时,会将清空购物车使用的连接挂起,从数据库连接池中新拿一个连接,执行DML语句后直接提交。而减少库存操作依旧会使用写入订单的数据库连接,并与写入订单操作一起提交。