范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

18个示例详解Spring事务传播机制

  什么是事务传播机制
  事务的传播机制,顾名思义就是多个事务方法之间调用,事务如何在这些方法之间传播。
  举个例子,方法 A 是一个事务的方法,方法 A 执行的时候调用了方法 B,此时方法 B 有无事务以及是否需要事务都会对方法 A 和方法 B 产生不同的影响,而这个影响是由两个方法的事务传播机制决定的。传播属性 Propagation 枚举
  Spring 对事务的传播机制在 Propagation 枚举中定义了7个分类:REQUIRED 默认SUPPORTS 支持MANDATORY 强制REQUIRES_NEW 新建NOT_SUPPORTED 不支持NEVER 从不NESTED 嵌套
  事务的传播机制,是 spring 规定的。因为在开发中,最简单的事务是,业务代码都处于同一个事务下,这也是默认的传播机制,如果出现的报错,所有的数据回滚。 但是在处理复杂的业务逻辑时,方法之间的调用,有以下的需求:调用的方法需要新增一个事务,新事务和原来的事务各自独立。调用的方法不支持事务调用的方法是一个嵌套的事务7种传播机制详解
  首先创建两个方法 A 和 B 实现数据的插入,插入数据A:public class AService {     public void A(String name) {         userService.insertName("A-" + name);     }  }
  插入数据B:public class BService {     public void B(String name) {         userService.insertName("B-" + name);     }  }
  使用伪代码创建 mainTest 方法和 childTest 方法   public void mainTest(String name)  {         // 存入a1         A(a1);         childTest(name);     }
  main 调用 test 方法,其中   public void childTest(String name)  {         // 存入b1         B(b1);        throw new RuntimeException();         // 存入 b2        B2(b2);     }
  以上伪代码,调用 mainTest 方法,如果mainTest 和childTest 都不使用事务的话,数据存储的结果是如何呢?
  因为都没使用事务,所以 a1 和 b1 都存到成功了,而之后抛出异常之后,b2是不会执行的。所以 a1 和 b1 都插入的数据,而 b2 没有插入数据。REQUIRED(默认事务)      /**      * Support a current transaction, create a new one if none exists.      * Analogous to EJB transaction attribute of the same name.      * 

This is the default setting of a transaction annotation. */ REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),   如果当前不存在事务,就新建一个事务。如果存在事务,就加入到当前事务。这是一个默认的事务。   示例1:根据场景举个例子,在 childTest 添加事务,设置传播属性为 REQUIRED,伪代码如下: public void mainTest(String name) { // 存入a1 A(a1); childTest(name); } @Transactional(propagation = Propagation.REQUIRED) public void childTest(String name) { // 存入b1 B(b1); throw new RuntimeException(); }   因为 mainTest 没有事务,而 childTest 又是新建一个事务,所以 a1 添加成功。在 childTest 因为抛出了异常,不会执行 b2 添加,而 b1 添加回滚。最终 a1 添加成功,b1没添加成功。   示例2:在 mainTest 和 childTest 都添加事务,传播属性都为 REQUIRED,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { // 存入a1 A(a1); childTest(name); } @Transactional(propagation = Propagation.REQUIRED) public void childTest(String name) { // 存入b1 B(b1); throw new RuntimeException(); }   根据 REQUIRED 传播属性,如果存在事务,就加入到当前事务。两个方法都属于同一个事务,同一个事务的话,如果有发生异常,则全部都回滚。所以 a1 和 b1 都没添加成功。SUPPORTS/** * Support a current transaction, execute non-transactionally if none exists. * Analogous to EJB transaction attribute of the same name. *

Note: For transaction managers with transaction synchronization, */   如果当前没有事务,则以非事务的方式运行。如果存在事务,就加入到当前事务。   示例3:childTest 添加事务,传播属性设置为 SUPPORTS,伪代码如下: public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.SUPPORTS) public void childTest(String name) { B(b1); throw new RuntimeException(); }   传播属性为 SUPPORTS,如果没有事务,就以非事务的方式运行。表明两个方法都没有使用事务,没有事务的话,a1、b1 都添加成功。   示例4:mainTest 添加事务,设置传播属性为 REQUIRED。childTest 添加事务,设置传播属性为 SUPPORTS,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.SUPPORTS) public void childTest(String name) { B(b1); throw new RuntimeException(); B2(b2); }   SUPPORTS 传播属性,如果存在事务,就加入到当前事务。mainTest 和 childTest 都属于同一个事务,而 childTest 抛出异常,a1 和b1 添加都回滚,最终 a1、b1 添加失败。MANDATORY/** * Support a current transaction, throw an exception if none exists. * Analogous to EJB transaction attribute of the same name. */   如果存在事务,就加入到当前事务。如果不存在事务,就报错。 这就说明如果想调用 MANDATORY 传播属性的方法,一定要有事务,不然就会报错。   MANDATORY 类似功能限制,必须要被有事务的方法的调用,不然就会报错。   示例5: 首先在 childTest 添加事务,设置传播属性为 MANDATORY,伪代码如下: public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.MANDATORY) public void childTest(String name) { B(b1); throw new RuntimeException(); B2(b2); }   在控制台直接报错:No existing transaction found for transaction marked with propagation "mandatory"   说明被标记为 mandatory 传播属性没找到事务,直接报错。因为 mainTest 没有事务,a1 添加成功。而 childTest 由于报错,b1 添加失败。   示例6: mainTest 添加事务,设置传播属性为 REQUIRED。childTest 添加事务,设置传播属性为 MANDATOR,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.MANDATORY) public void childTest(String name) { B(b1); throw new RuntimeException(); }   如果存在事务,就把事务加入到当前事务。同一个事务中 childTest 抛出异常,a1 和 b1 添加被回滚,所以a1 和 b1添加失败。REQUIRES_NEW /** * Create a new transaction, and suspend the current transaction if one exists. * Analogous to the EJB transaction attribute of the same name. *

NOTE: Actual transaction suspension will not work out-of-the-box */   创建一个新的事务。如果存在事务,就将事务挂起。   无论是否有事务,都会创建一个新的事务。   示例7:childTest 添加事务,设置传播属性为 REQUIRES_NEW,伪代码如下: public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void childTest(String name) { B(b1); throw new RuntimeException(); }   mainTest 不存在事务,a1 添加成功,childTest 新建了一个事务,报错,回滚 b1。所以 a1 添加成功,b1 添加失败。   示例8:mainTest 添加事务,设置传播属性为 REQUIRED。childTest 添加事务,设置传播属性为 REQUIRES_NEW,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void childTest(String name) { B(b1); throw new RuntimeException(); }   mainTest 创建了一个事务,childTest 新建一个事务,在 childTest 事务中,抛出异常,b1 回滚,异常抛到 mainTest 方法,a1 也回滚,最终 a1 和 b1 都回滚。   示例9:在示例8中,如果不想让 REQUIRES_NEW 传播属性影响到被调用事务,将异常捕获就不会影响到被调用事务。 @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); try { childTest(name); } catch (Exception e) { e.printStackTrace(); } } @Transactional(propagation = Propagation.REQUIRES_NEW) public void childTest(String name) { B(b1); throw new RuntimeException(); }   childTest 抛出了异常,在 mainTest 捕获了,对 mainTest 没有影响,所以 b1 被回滚,b1 添加失败,a1 添加成功。   示例10:mainTest 设置传播属性为 REQUIRED,并在 mainTest 抛出异常。childTest 同样设置 REQUIRES_NEW 传播属性,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); throw new RuntimeException(); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void childTest(String name) { B(b1); B2(b2); }   childTest 是一个新建的事务,只要不抛出异常是不会回滚,所以 b1 添加成功,而 mainTest 抛出了异常,a1 添加失败。   REQUIRES_NEW 传播属性如果有异常,只会从被调用方影响调用方,而调用方不会影响调用方,即 childTest 抛出异常会影响 mainTest,而 mainTest 抛出异常不会到 childTest。NOT_SUPPORTED /** * Execute non-transactionally, suspend the current transaction if one exists. * Analogous to EJB transaction attribute of the same name. *

NOTE: Actual transaction suspension will not work out-of-the-box */   无论是否存在当前事务,都是以非事务的方式运行。   示例11:childTest 添加事务,设置传播属性为 NOT_SUPPORTED,伪代码如下: public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.NOT_SUPPORTED) public void childTest(String name) { B(b1); throw new RuntimeException(); }   NOT_SUPPORTED 都是以非事务的方式执行,childTest 不存在事务,b1 添加成功。而 mainTest 也是没有事务,a1 也添加成功。   示例12:childTest 添加事务,设置传播属性为 NOT_SUPPORTED,mainTest 添加默认传播属性 REQUIRED,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.NOT_SUPPORTED) public void childTest(String name) { B(b1); throw new RuntimeException(); }   其中 childTest 都是以非事务的方式执行,b1 添加成功。而 mainTest 存在事务,报错后回滚,a1 添加失败。NEVER /** * Execute non-transactionally, throw an exception if a transaction exists. * Analogous to EJB transaction attribute of the same name. */   不使用事务,如果存在事务,就抛出异常。   NEVER 的方法不使用事务,调用 NEVER 方法如果有事务,就抛出异常。   示例13:childTest 添加 NEVER 传播属性,伪代码如下: public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.NEVER) public void childTest(String name) { B(b1); throw new RuntimeException(); B2(b2); }   NEVER 不使用事务,mainTest 也不使用事务,所以 a1 和 b1 都添加成功,b2添加失败。   示例14: mainTest 添加 REQUIRED 传播属性,childTest 传播属性设置为 NEVER,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.NEVER) public void childTest(String name) { B(b1); throw new RuntimeException(); }   mainTest 存在事务,导致 childTest 报错,b1添加失败,childTest 抛错到 mainTest,a1 添加失败。NESTED/** * Execute within a nested transaction if a current transaction exists, * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB. *

Note: Actual creation of a nested transaction will only work on specific */   如果当前事务存在,就运行一个嵌套事务。如果不存在事务,就和 REQUIRED 一样新建一个事务。   示例15: childTest 设置 NESTED 传播属性,伪代码如下: public void mainTest(String name) { A(a1); childTest(name); } @Transactional(propagation = Propagation.NESTED) public void childTest(String name) { B(b1); throw new RuntimeException(); }   在 childTest 设置 NESTED 传播属性,相当于新建一个事务,所以 b1 添加失败, mainTest 没有事务,a1 添加成功。   示例16:设置 mainTest 传播属性为 REQUIRED,新建一个事务,并在方法最后抛出异常。 childTest 设置属性为 NESTED,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); childTest(name); throw new RuntimeException(); } @Transactional(propagation = Propagation.NESTED) public void childTest(String name) { B(b1); B2(b2); }   childTest 是一个嵌套的事务,当主事务的抛出异常时,嵌套事务也受影响,即 a1、b1 和 b2 都添加失败。和示例10不同的是,示例10不会影响 childTest 事务。NESTED 和 REQUIRED_NEW 的区别:REQUIRED_NEW 是开启一个新的事务,和调用的事务无关。调用方回滚,不会影响到 REQUIRED_NEW 事务。NESTED 是一个嵌套事务,是调用方的一个子事务,如果调用方事务回滚,NESTED 也会回滚。   示例17:和示例16一样,在 mainTest 设置传播属性为 REQUIRED,childTest 设置传播属性为 NESTED,不同的是,在 mainTest 捕获 childTest 抛出的异常,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); try { childTest(name); } catch (RuntimeException e) { e.printStackTrace(); } } @Transactional(propagation = Propagation.NESTED) public void childTest(String name) { B(b1); B2(b2); throw new RuntimeException(); }   childTest 是一个子事务,报错回滚,b1 和 b2 都添加失败。而 mainTest 捕获了异常,不受异常影响,a1 添加成功。   示例18:将示例2改造一下,mainTest 捕获 childTest 抛出的异常,伪代码如下: @Transactional(propagation = Propagation.REQUIRED) public void mainTest(String name) { A(a1); try { childTest(name); } catch (RuntimeException e) { e.printStackTrace(); } } @Transactional(propagation = Propagation.REQUIRED) public void childTest(String name) { B(b1); B2(b2); throw new RuntimeException(); }   mainTest 和 childTest 两个方法都处于同一个事务,如果有一个方法报错回滚,并且被捕获。整个事务如果还有数据添加就会抛出 Transaction rolled back because it has been marked as rollback-only 异常,同一个事务,不能出现有的回滚了,有的不回滚,要么一起回滚,要不一起执行成功。所以全部数据都添加失败。对比示例17和示例18,NESTED 和 REQUIRED 的区别: REQUIRED 传播属性表明调用方和被调用方都是使用同一个事务,被调用方出现异常,无论异常是否被捕获,因为属于同一个事务,只要发生异常,事务都会回滚。 NESTED 被调用方出现异常,只要异常被捕获,只有被调用方事务回滚,调用方事务不受影响。总结   传播属性   总结   REQUIRED   默认属性,所有的事务都处于同一个事务下,出现异常,不管是否捕获所有事务回滚   SUPPORTS   如果不存事务,就以非事务的方式运行,存在事务就加入该事务   MANDATORY   强制调用方添加事务,如果不存在事务就报错,存在事务就加入该事务   REQUIRES_NEW   无论调用方是否存在事务,都会创建新的事务,并且调用方异常不会影响 REQUIRES_NEW事务   NOT_SUPPORTED   无论是否调用方是否存在事务,都是以非事务的方式执行,出现异常也会回滚   NEVER   不用事务,存在事务就报错,和 MANDATORY 相反   NESTED   嵌套事务,新建一个子事务,事务执行相互独立,如果调用方出现异常,直接回滚测试源码传播属性源码参考带你读懂Spring 事务——事务的传播机制


卧铺车厢内的插座烧手机充电器,电压不稳昨天坐的长春到三亚的Z385次列车,上车之后,玩手机游戏看视频刷头条看小说等打发时间。可时间久了,手机没电了,只剩下百分之十几的电了,要充电了,没有充电宝,只能拿着充电器,沿着卧铺濂溪区比浔阳区的教育水平差很多,什么时候有提升啊?4月19日,据江西公共资源交易网消息八里湖新区赛城湖新城中学(九江同文中学赛城湖校区)建设项目发布招标公告!到现在为止,九江一中,二中,三中都在八里湖有新校区了,九江小学也在八里湖200元级TWS耳机也有一耳朵惊喜?SoundPEATSTrueAir2体验分享苹果为什么牛?因为它总能颠覆传统就像当年凭借一己之力,带动智能手机飞速发展,让诺基亚这艘巨轮以迅雷不及掩耳盗铃之势消失在智能手机的汪洋大海之中,在苹果的推动下,TWS真无线耳机时代九江濂溪区个人社保的问题。今天刚好要去社保局打印发票。然后看到那个工作人员的那个工作台上面。贴着个人是我犯的这个通知流程一,使用微信公众号缴纳个人社保费(可代替他人缴纳)1,在微信搜索公众号江西省税务局或者UNIK释放智能体验当你上车后,UNIK会自动刷脸识别车主身份,并根据相关联的记忆功能,会将座椅后视镜调整到你之前的位置,哪怕刷脸着车也都是可以的。UNIK还可实现隔空手势交互,能够识别车上所有人的手江西一村民霸气嫁女江西一村民嫁女在院子里拉起了数条雷人条幅霸气却又温暖为了表示对爱女的挚爱和不舍,拉起了霸气条幅。小姨子说这个横幅告诉你,天大地大我姐最大小舅子霸气警告我姐温柔端庄回到娘家眼中有泪身联合三星研发双模5G芯片Exynos980,vivo站在当前5G领域制高点近日,vivo联合三星在京举行媒体沟通会,展示了双模5GAI芯片联合研发成果Exynos980,并官宣12月发布的X30系列新品将首发搭载。据了解,Exynos980集成了出色的双日本制裁韩国,三星内存条恐涨价,却不料遇到拼多多双11今年七月,日本制裁韩国,启动对韩半导体的出口管制。一时间人心惶惶,纷纷猜测,韩国的内存条是不是借机又要开始涨价了。要知道,在2017年为了挽回中国手机市场占有量下滑带来的损失,三星中年人的妥协Mac换surface,希捷小宝备移动固态体验前言大家好,我是加勒比考斯,我又来了!最近又开始折腾,由于工作内容有些变化,需要经常移动,之前用的一台Macmini如果用来办公就十分不方便,所以想换一台便捷的笔记本,我在iPad没时间解释了快上车,vivo的双WIFI让你感受不一样的网速相信大家多少都有过这样的体验,明明是在同一个位置,同一个网络环境之下,为什么有的人因为网络差得落地成盒,有的却能借助着流畅的网络顺利吃鸡。下次再遇到这样的情况,除了考虑的吃鸡技术外一招解决远光困扰,魔洁兔偏光驾驶镜T1潮流黄让开车更省心远光狗也许算不上最流氓的驾驶行为,但绝对能排到前三,经常晃得对向司机睁不开眼,看不清前方路况。但作为新时代青年,我们不能与会车不关远光灯的朋友硬碰硬,上演要瞎一起瞎的戏码,以至于不
最漂亮的水中倒影照片,你敢发出来让大家欣赏吗?漂亮的水中倒影照片,人人看了都喜欢,我也喜欢水中的倒影,凡是看到好的水中到影风景,我都喜欢用手机即刻拍下来珍藏起来,自己慢慢的欣赏美丽的水中倒影风景。下面是本人在上海的世纪公园川杨关于Python的Selenium框架全解,一篇完整的说明书目录selenium基础语法一环境配置1安装环境安装selenium第三方库pipinstallselenium下载浏览器驱动Firefox浏览器驱动geckodriverChro3月1日微信支付宝收款都有哪些新规?你知道多少?微信支付宝3月1日新规定,具体发布的新规定是什么?主要有三点1个人收款代码远程收款功能有限。2商家不能用微信支付宝的个人收据收款。3。收款代码分为个人和特约商人两大类,实行分类管理加密货币使得俄罗斯更容易规避制裁近日,据美国媒体报道,一些区块链专家表示,西方对俄罗斯实施的金融制裁措施变得越来越容易被规避,部分原因是俄罗斯正大量采用加密货币。据美国有线电视新闻网(CNN)2月24日报道,随着Java集合类框架详解Java集合框架概述集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java。util包下,但支持多线程的集合类位于java。util。concurrent包下。Java中国智能终端产品行业深度研究与产业竞争格局中国产业研究报告网发布的20222028年中国智能终端产品行业深度研究与产业竞争格局报告共十一章。首先介绍了智能终端产品行业市场发展环境智能终端产品整体运行态势等,接着分析了智能终微信新更新的版本,哪些小程序好用?自从12月微信更新了新版本,从聊天窗口拉下就能找到已关注的小程序。新上线了微信跳一跳小程序游戏,可以说小程序一下子火了起来。我们都会有这样的问题,还有什么好用或者好玩的小程序吗?答关于元宇宙的现实应用猜想其实我一直有自不量力的想给华为总部写信的冲动,想谈一谈关于元宇宙的现实应用,其实元宇宙这项技术确实很先进,但再先进的技术也应该归于现实的应用,我非常建议华为将元宇宙技术用于现在的华国产电视销售第一名,打败日本索尼成全球第三,海信也不是对手随着时代的发展,人们的日常生活中出现了许多新奇的产品,在没有通电的年代,人们就只能通过看皮影戏来解乏。随着有电时代的到来,人们的生活更是发生了翻天覆地的变化,先是出现了电视机,后出微型电动机可产生335马力。仅重28。58公斤这款名为Quark的发动机仅重28。58公斤,声称拥有业内最佳的扭矩重量比。瑞典超级跑车制造商科尼赛克长期以来一直是创新技术的发源地,它在其新型电动机中得到了体现。这款名为Quar霍老师谈CRM我独的家提出一关个于私域概的念私域,是就微信CRM。CRM是什么?CRM就是客户关系理管。也就是说,私,域就是我们用信微来管理自己的客户包,括引流包,括运营,包复括购,包括变裂。第