Spring事務傳播行為實戰

一、什么是事務傳播行為?事務傳播行為(propagation behavior)指的就是當一個事務方法被另一個事務方法調用時,這個事務方法應該如何運行 。
例如:methodA方法調用methodB方法時,methodB是繼續在調用者methodA的事務中運行呢 , 還是為自己開啟一個新事務運行 , 這就是由methodB的事務傳播行為決定的 。
二、事務傳播行為類型Spring在TransactionDefinition接口中規定了7種類型的事務傳播行為 。事務傳播行為是Spring框架獨有的事務增強特性,這是Spring為我們提供的強大的工具箱,使用事務傳播行為可以為我們的開發工作提供許多便利 。
兩大類

  • 支持事務的傳播
  • 不支持事物的傳播
七小種
  • REQUIRED:(支持事務)如果當前沒有事務 , 就創建一個新事務,如果當前存在事務 , 就加入該事務(Spring默認)
  • SUPPORTS:(支持事務)如果當前存在事務,就加入該事務 , 如果當前不存在事務 , 就以非事務執行
  • MANDATORY:(支持事務)如果當前存在事務,就加入該事務 , 如果當前不存在事務,就拋出異常
  • REQUIRES_NEW:(支持事務)創建新事務,無論當前存不存在事務,都創建新事務
  • NOT_SUPPORTED:(不支持事務)如果當前存在事務,就把當前事務掛起
  • NEVER:(不支持事務)以非事務方式執行,如果當前存在事務 , 則拋出異常
  • NESTED:(支持事務)如果當前存在事務,則在嵌套事務內執行 。如果當前沒有事務 , 就創建一個新事務
三、事務傳播行為實戰**說明:**父方法插入表ks_a、子方法插入表ks_b表結構:
CREATE TABLE `ks_a` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',`name` varchar(20) DEFAULT NULL COMMENT '姓名',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='測試A';CREATE TABLE `ks_b` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',`age` tinyint(4) DEFAULT NULL COMMENT '年齡',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='測試B';1、REQUIRED1.1、父方法無事務,子方法開啟事務,子方法報錯 public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insertError(ksB); } @Transactional(propagation = Propagation.REQUIRED) public void insertError(KsB ksB) {ksBDao.insert(ksB);throw new RuntimeException("子方法報錯"); }結果:ks_a數據插入成功,ks_b數據回滾
Spring事務傳播行為實戰

文章插圖
Spring事務傳播行為實戰

文章插圖
1.2、父方法開啟事務,子方法開啟事務,父方法報錯 @Transactional public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insert(ksB);throw new RuntimeException("主方法報錯"); } @Transactional(propagation = Propagation.REQUIRED) public void insert(KsB ksB) {ksBDao.insert(ksB); }結果:兩表數據都回滾了
Spring事務傳播行為實戰

文章插圖
Spring事務傳播行為實戰

文章插圖
1.3、父方法開啟事務,子方法開啟事務,子方法報錯 @Transactional public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insertError(ksB); } @Transactional(propagation = Propagation.REQUIRED) public void insertError(KsB ksB) {ksBDao.insert(ksB);throw new RuntimeException("子方法報錯"); }結果:兩表數據都回滾了
Spring事務傳播行為實戰

文章插圖
Spring事務傳播行為實戰

文章插圖
總結父方法無事務,子方法開啟新事務父方法有事務,子方法和父方法共用一個事務(無論父、子方法報錯,整體回滾)
2、SUPPORTS2.1、父方法無事務,子方法開啟事務,子方法報錯 public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insertError(ksB); } @Transactional(propagation = Propagation.SUPPORTS) public void insertError(KsB ksB) {ksBDao.insert(ksB);throw new RuntimeException("子方法報錯"); }結果:數據都插入成功
Spring事務傳播行為實戰

文章插圖
Spring事務傳播行為實戰

推薦閱讀