Spring事务的传播级别

一、简单说明

二、具体案例描述

1.PROPAGATION_REQUIRED

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        doSufSomething;}
@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodB(){        doSomething;} 复制代码

复制代码

在两个方法的事务传播级别都是 PROPAGATION_REQURIED 的时候。如果调用方法 A,会开启一个事务,在方法 A 内部调用方法 B,由于方法 A 已经存在开启尚未提交的事务,方法 B 不会就不会再开启一个新的事务,方法 B 会直接加入方法 A 的事务中执行,这样如果在执行方法 B 的时候出了异常导致事务回滚,则 B 的方法和 A 的方法都会回滚。如果 A 的 doPreSomething()和方法 B 都执行成功了,但是在执行 doSufSomething()方法的时候抛出了异常导致事务回滚,则 doSufSomething()、methodB()和 doPreSomething()都会回滚。如果不通过方法 A 而单独调用方法 B,则会开启一个事务。PROPAGATION_REQURIED 所有方法公用一个事务,要么一起成功提交,要么一起失败回滚。如果嵌套执行的方法要求一起执行成功或者一起回滚,则选择该事物传播级别。

执行逻辑:

开启事务执行方法A的 doPreSomething 执行方法 B 执行方法 A 的 doSufSomething 提交或回滚事务

2.PROPAGATION_REQUIRED_NEW

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        dosufSomething;}
@Transactional(propagation=PROPAGATION_REQUIRED_NEW)pubilc void methodB(){       doSomething;} 复制代码

复制代码

在事务的隔离级别是 PROPAGATION_REQUIRED_NEW 的时候。如果调用方法 A,会开启一个事务,在方法内部调用方法 B,方法 B 会自己再开启一个事务,然后方法 B 在自己的事务内部执行,如果方法 B 执行失败抛出异常,那么事务 B 会进行回滚,事务 A 不会受到影响可以继续执行,如果在方法 B 执行成功,方法 B 的事务会单独进行提交;B 提交事务之后接着执行 A 的 doSufSomething()方法,如果执行成功提交 A 的事务,如果抛出异常,则只回滚 A 的事务,对 B 的事务不会进行影响,也就说 B 的事务不会进行回滚。如果不通过方法 A 而单独调用方法 B,则会开启一个事务。PROPAGATION_REQURIED_NEW 所有方法使用各自的事务,各自提交或者回滚各自的事务,相互之间不会造成影响。如果嵌套执行的方法要求各自事务独立,不能进行相互影响,则选择本事务传播级别。

执行逻辑

开启事务执行方法A的 doPreSomething 开启另一个事务 2 执行方法 B 提交或者回滚事务 2 执行方法 A 的 doSufSomething 提交或回滚事务

3.PROPAGATION_SUPPORTS

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        doSufSomething;}
@Transactional(propagation=PROPAGATION_SUPPORTS)pubilc void methodB(){       doSomething;} 复制代码

复制代码

在事务的隔离级别是 PROPAGATION_SUPPORTS 的时候。如果调用方法 A,会开启一个事务,在方法 A 内部调用方法 B,由于方法 A 已经存在开启尚未提交的事务,方法 B 会直接加入方法 A 的事务中执行,这样如果在执行方法 B 的时候出了异常导致事务回滚,则 B 的方法和 A 的方法都会回滚。如果 A 的 doPreSomething()和方法 B 都执行成功了,但是在执行 doSufSomething()方法的时候抛出了异常导致事务回滚,则 doSufSomething()、methodB()和 doPreSomething()都会回滚。如果不通过方法 A 而单独调用方法 B,则方法 B 不会开启事务,直接会以非事务的方式执行。PROPAGATION_SUPPORTS 如果存着事务就加入和 PROPAGATION_REQUIRED 传播级别一致,如果当前不存在事务,则不会创建新的事务,以非事务的方式执行。如果嵌套执行的方法要求一起执行成功或者一起回滚,单独执行时候以非事务方式执行,则选择该事物传播级别。

执行逻辑:

开启事务执行方法A的 doPreSomething 执行方法 B 执行方法 A 的 doSufSomething 提交或回滚事务

4.PROPAGATION_NOT_SUPPORTED

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        doSufSomething;}
@Transactional(propagation=PROPAGATION_NOT_SUPPORTED)pubilc void methodB(){        doSomething;} 复制代码

复制代码

在事务的隔离级别是 PROPAGATION_NOT_SUPPORTED 的时候。如果调用方法 A,会开启一个事务,在方法 A 内部调用方法 B,由于方法 A 已经存在开启尚未提交的事务,方法 B 不允许在事务内部执行,这时候事务就会挂起,在非事务的状态中执行方法 B,不管方法 B 是执行成功还是执行失败,都不会对当前事务造成影响。如果 A 的 doPreSomething()和方法 B 都执行成功了,但是在执行 doSufSomething()方法的时候抛出了异常导致事务回滚,则 doSufSomething()和 doPreSomething()会回滚,而方法 B 不会受到任何影响,因为它是在非事务中执行的。如果不通过方法 A 而单独调用方法 B,则方法 B 不会开启事务,直接会以非事务的方式执行。PROPAGATION_NOT_SUPPORTED 如果存着事务就挂起当前事务,以非事务的方式运行自己,如果当前不存在事务,则不会创建新的事务,以非事务的方式执行。如果嵌套执行的方法要求内部嵌套方法不会对外部方法事务造成影响并且内部方法不需要事务,单独执行时候以非事务方式执行,则选择该事物传播级别。

执行逻辑:

开启事务执行方法A的 doPreSomething 挂起事务执行方法 B 重新启用挂起的事务执行方法 A 的 doSufSomething 提交或回滚事务

5.PROPAGATION_MANDATORY

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        doSufSomething;}
@Transactional(propagation=PROPAGATION_MANDATORY)pubilc void methodB(){       doSomething;} 复制代码

复制代码

在事务的隔离级别是 PROPAGATION_MANDATORY 的时候。如果调用方法 A,会开启一个事务,在方法 A 内部调用方法 B,由于方法 A 已经存在开启尚未提交的事务,方法 B 会直接加入方法 A 的事务中执行,这样如果在执行方法 B 的时候出了异常导致事务回滚,则 B 的方法和 A 的方法都会回滚。如果 A 的 doPreSomething()和方法 B 都执行成功了,但是在执行 doSufSomething()方法的时候抛出了异常导致事务回滚,则 doSufSomething()、methodB()和 doPreSomething()都会回滚。如果不通过方法 A 而单独调用方法 B,则方法 B 会直接报错,因为方法 B 的事务传播级别是 PROPAGATION_MANDATORY,而其不允许在没有事务的环境下执行。PROPAGATION_SUPPORTS 如果存着事务就加入和 PROPAGATION_REQUIRED 传播级别一致,如果当前不存在事务,会直接进行报错,不允许以非事务的方式执行。如果嵌套执行的方法要求一起执行成功或者一起回滚,单独执行时候不允许以非事务方式执行,则选择该事物传播级别。

执行逻辑:

开启事务执行方法A的 doPreSomething 执行方法 B 执行方法 A 的 doSufSomething 提交或回滚事务

6.PROPAGATION_NEVER

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        doSufSomething;}
@Transactional(propagation=PROPAGATION_NEVER)pubilc void methodB(){        doSomething;} 复制代码

复制代码

在事务的隔离级别是 PROPAGATION_NERVR 的时候。如果调用方法 A,会开启一个事务,在方法 A 内部调用方法 B,由于方法 A 已经存在开启尚未提交的事务,方法 B 的传播级别为 PROPAGATION_NEVER,其不允许在事务内部执行,所以这时候就会直接报错。如果不通过方法 A 而单独调用方法 B,则方法 B 会直接在没有事务的环境中执行。PROPAGATION_NERVER 如果存着事务就直接报错,如果当前不存在事务,会以非事务的方式执行。如果嵌套执行的方法要求内部方法不允许在事务中执行,单独执行时候必须以非事务方式执行,则选择该事物传播级别。

执行逻辑:

开启事务执行方法A的 doPreSomething 执行方法 B,直接报错回滚事务

7.PROPAGATION_NESTED

@Transactional(propagation=PROPAGATION_REQUIRED)pubilc void methodA(){        doPreSomething;        methodB();        doSufSomething;}
@Transactional(propagation=PROPAGATION_NESTED)pubilc void methodB(){        doSomething;} 复制代码

复制代码

在事务的隔离级别是 PROPAGATION_NESTED 的时候。如果调用方法 A,会开启一个事务,在方法 A 内部调用方法 B,由于方法 A 已经存在开启尚未提交的事务,方法 B 的传播级别为 PROPAGATION_NESTED,会加入这个事务当中,但是在执行到方法 B 之前会创建一个事务的回滚点(savepoint),然后执行方法 B,如果方法 B 执行失败了,事务会进行回滚,但是这时指挥回滚到回滚点,也就是之后回滚 B 的操作,外部方法的操作不会回滚;如果 B 执行成功了,接着执行 A 的 doSufSomething()方法,如果执行出错,则会回滚整个事务,也就是 doSufSomething()、methodB()和 doPreSomething()的执行都会进行回滚。如果直接调用方法 B,则会开启一个事务,和 PROPAGATION_REQUIRED 传播级别一致。如果嵌套执行的方法要求内部方法出错只回滚自己,外部方法执行失败回滚所有,单独执行时候自动开启一个执行,则选择该事物传播级别。

执行逻辑:

开启事务执行方法A的 doPreSomething 创建回滚点 savepoint 执行方法 B,失败只回滚到 savepoint 执行方法 A 的 doSufSomething 提交或回滚事务

posted @ 2022-04-28 15:18  Linux运维阿铭  阅读(76)  评论(0编辑  收藏  举报