ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring-七种事务传播特性

2021-01-16 14:31:02  阅读:610  来源: 互联网

标签:事务 七种 老大 Spring 小弟 PROPAGATION methodB ServiceB


以下面2个方法为例:

@Service
public class DaoService {

    @Transactional
    public void laoda() {
        System.out.println("老大的方法");
        //在老大方法里面调用小弟方法
        xiaodi();
    }

    @Transactional
    public void xiaodi() {
        System.out.println("小弟的方法");
    }

}

Spring总共给了7种事务的传播特性:
就是多个事务方法相互调用时,事务如何在这些方法间传播

问题:什么叫传播特性, 拿上面两个方法来说,老大方法调用小弟方法,老大方法里面发生异常小弟事务怎么处理?

分三类:

1.=死活不要事务===

1) PROPAGATION_NEVER: 没有就非事务执行,有就抛异常

eg: 老大调用小弟方法,小弟不允许有事务,当小弟发现老大有事务时,直接抛异常,我不干,没有就正常运行

2) PROPAGATION_NOT_SUPPORTED: 没有就非事务执行,有就直接挂起,然后非事务执行

eg: 老大调用小弟方法,小弟不允许有事务,当小弟发现老大有事务时,就将老大的事务挂起,换句话说就是老大的事务管不着小弟,小弟自己非事务运行,不受老大事务约束

2.=事务可有可无==

3). PROPAGATION_SUPPORTS: 如果有事务就用,没有就非事务执行

eg: 老大调用小弟方法,小弟会去看下老大是否有事务,有就用,没有就算了,非事务运行

3.=必须有事务的==

4).PROPAGATION_REQUIRED_NEW: 有没有都会新建事务,如果原来有,就将原来的挂起;

eg: 老大调用小弟方法,小弟方法必须要有事务,它会去看下老大有没有事务,老大有就将老大的挂起,反正不会用老大的事务,自己新建一个新的。小弟由于是一个新的事务,所以不受老大事务影响,但是如果小弟抛异常,小弟回滚,老大就要看下是否处理异常,没有处理也回滚,处理了就不会回滚
启动一个新的, 不依赖于环境的 “内部” 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.
比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务。
1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。
2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try…catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

5). PROPAGATION_NESTED: 如果没有,就新建一个事务,如果有,就在当前事务中嵌套其他事务;

eg:老大调用小弟方法,小弟方法必须要有事务,它会去看下老大有没有事务,有就用老大的事务,没有就自己新建一个事务,嵌套其中。当小弟发生异常,会回滚到回滚点 savepoint.,也就是嵌套事务点,外界事务此时不会回滚,除非他对异常没有进行处理,但是如果老大发生异常,由于是嵌套,小弟必然回滚。

开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.

比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_NESTED,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的子事务并设置savepoint,等待ServiceB.methodB的事务完成以后,他才继续执行。。因为ServiceB.methodB是外部事务的子事务,那么
1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB也将回滚。
2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try…catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是:
PROPAGATION_REQUIRES_NEW 完全是一个新的事务,它与外部事务相互独立; 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back.

在 spring 中使用 PROPAGATION_NESTED的前提:

  1. 我们要设置 transactionManager 的 nestedTransactionAllowed 属性为 true, 注意, 此属性默认为 false!!!
  2. java.sql.Savepoint 必须存在, 即 jdk 版本要 1.4+
  3. Connection.getMetaData().supportsSavepoints() 必须为 true, 即 jdbc drive 必须支持 JDBC 3.0

6) PROPAGATION_REQUIRED: 如果没有,就新建一个事务,如果有,就加入当前事务.

eg:老大调用小弟方法,小弟方法必须要有事务,它会去看下老大有没有事务,有就用老大的事务,没有就自己新建一个事务。 如果老大有事务,此时小弟使用老大事务,他们是一个整体,要么同时成功,要么同时失败,但是如果老大没有事务,小弟自己新建了一个事务,那么即使小弟事务抛异常也不会影响老大,因为老大没事务.

7). PROPAGATION_MANDTORY: 如果没有就抛异常,如果有就是使用当前事务

eg:老大调用小弟方法,小弟方法必须要有事务,它会去看下老大有没有事务,有就用老大的事务,没有就抛异常,反正自己不会去新建事务。
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常

标签:事务,七种,老大,Spring,小弟,PROPAGATION,methodB,ServiceB
来源: https://blog.csdn.net/Hmj050117/article/details/112690078

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有