hi ,大家好,繼續為大家帶來Spring事務傳播機制的相關知識
文章目錄
- 🤗1.事務傳播機制是什么
- 🤗2.事務傳播機制作用
- 🤗3.事務傳播機制
🤗1.事務傳播機制是什么
定義了多個包含了事務的?法,相互調?時,事務是如何在這些?法間進?傳遞的
🤗2.事務傳播機制作用
事務隔離級別是保證多個并發事務執?的可控性的(穩定性的),而事務傳播機制是保證?個事務在多個調用方法間的可控性的(穩定性的)
上面的圖片很好的解釋了事務傳播機制和事務隔離級別的流程
🤗3.事務傳播機制
Spring事務傳播機制定義了在多個事務方法相互調用時,不同事務方法間事務處理的行為方式。Spring框架提供了7種不同的事務傳播行為方式,分別是:
- REQUIRED:默認的傳播行為,如果當前存在事務,則加入該事務,否則創建一個新事務。
這個來通俗的解釋一下,如果當前方法沒有開啟事務,就會創建一個新的事務,如果存在事務就會加入該事務
我們在用代碼驗證一下
因為此時的級別默認是required,所以應該是一個大事務,有一個有異常 ,其余的也就添加失敗
可以從數據庫中看到,并未添加數據
- SUPPORTS:如果當前存在事務,則加入該事務,否則不使用事務。
如果A 沒有開啟事務,那么就以非事務的方式運行,后面的方法看到該調用鏈沒有事務就也會擺爛,因此即使報了異常,也繼續添加,
看代碼
3 MANDATORY:當前方法必須在事務中執行,存在事務,就會加入該事務,如果不存在事務,則拋出異常。
4.REQUIRES_NEW:表示創建?個新的事務,如果當前存在事務,則把當前事務掛起。也就是說不管外部?法是否開啟事務,Propagation.REQUIRES_NEW 修飾的內部?法會新開啟??的事務,且開啟的事務相互獨?,互不?擾。
5.NOT_SUPPORTED:以?事務?式運?,如果當前存在事務,則把當前事務掛起
6.NEVER:當前方法不能在事務中執行,如果存在事務,則拋出異常。
可以清楚的看到沒有插入
控制臺連受影響的行數都沒有打印,直接拋出異常
這個NESTED比較繞😭,我們一起努力,沖沖沖!😜
7.NESTED:創建一個嵌套事務,如果當前存在事務,則將該事務作為嵌套事務的父事務,如果父事務提交,則嵌套事務會提交,否則回滾。
如果當前沒有事務,則該取值等價于 PROPAGATION_REQUIRED。
執行流程
當沒有事務,創建事務,后續方法會生成嵌套事務,并且有一個保存點,一旦該事務出現問題,就會回滾到上一個事務保存點,不會影響其他事務的執行
package com.example.demo.controller;import com.example.demo.model.Userinfo;
import com.example.demo.service.UserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.pattern.PathPattern;//測試類@RestController@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.REQUIRED)public int add(){Userinfo userinfo=new Userinfo();userinfo.setUsername("老七");userinfo.setPassword("123");int result= userService.add(userinfo);System.out.println("受影響的行數是"+result);userService.insert(userinfo);return result;}
}
package com.example.demo.service;import com.example.demo.mapper.UserMapper;
import com.example.demo.model.Userinfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactional(propagation = Propagation.NESTED)public int add(Userinfo userinfo){int result=userMapper.add(userinfo);System.out.println("受影響的行數"+result);return result;}@Transactional(propagation = Propagation.NESTED)public int insert(Userinfo userinfo){int result=userMapper.add(userinfo);System.out.println("受影響的行數"+result);int num=10/0;return result;}
}
數據庫是啥也沒插入的,為啥呢?不是說會回滾到上一個事務保存點嗎?所以應該插入一條,為啥一條也沒有
因為:
第三個出了問題,那么創建事務的作為調用方,一定可以感知到異常,那么整個事務就會回滾,所以一條都不會插入
所以某個方法報異常不要讓總的調用者感知到,就不會全部回滾,那么可以采用如下方式
修改這里的代碼,讓該方法感知到異常即可,不讓總方法感知到,那么就會執行回滾操作,回滾到上一個事務保存點,所以只會插入一條數據
在寫這個例子的時候,我們特意修改,不在add方法里面調用insert方法,而是在userController中調用,為什么呢?
🤗🤗🤗因為NESTED嵌套NESTED的時候,上一個NESTED保存點設置不上,這兩個保存點會進行合并,合并成一個臨時任務,那么一個掛掉,兩個都掛了,所以在總的調用方法中調用它,才能有效果
再舉一個例子:
公司雇了一個清潔工A,清潔工自己有又雇了一個清潔工B,當清潔B干了壞事,那么公司就會把A和B同時開除,當公司雇了兩個清潔工,其中一個清潔工出了問題,就開掉出問題的那個就好,沒出問題的留下~
這個例子就對應了代碼的執行過程~
今天就講到這里,我們下期再見,886!