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

你可能感兴趣的:(Java基础,java,spring,spring,boot)