一蝌焚、SaaS多租戶簡介
多租戶技術(shù)是一種軟件架構(gòu)技術(shù),它是在探討與實(shí)現(xiàn)如何于多用戶的環(huán)境下共用相同的系統(tǒng)或程序組件誓斥,并且仍可確保各用戶間數(shù)據(jù)的隔離性只洒。它是為共用的數(shù)據(jù)中心內(nèi)如何以單一系統(tǒng)架構(gòu)與服務(wù)提供多數(shù)客戶端相同甚至可定制化的服務(wù),并且仍可保障客戶的數(shù)據(jù)隔離劳坑。簡單來說是一個(gè)單獨(dú)的實(shí)例可以為多個(gè)組織服務(wù)毕谴。
多租戶是SaaS(Software-as-a-Service)下的一個(gè)概念,意思為軟件及服務(wù),即通過網(wǎng)絡(luò)提供軟件服務(wù)涝开。SaaS平臺供應(yīng)商將應(yīng)用軟件統(tǒng)一部署在自己的服務(wù)器上循帐,客戶端可以根據(jù)工作的實(shí)際需求,通過互聯(lián)網(wǎng)向廠商租用所需的應(yīng)用軟件服務(wù)舀武,按定購的服務(wù)多少和時(shí)間長短向廠商支付費(fèi)用惧浴,并通過互聯(lián)網(wǎng)獲得SaaS平臺供應(yīng)商提供的服務(wù)。
SaaS服務(wù)尤其利于一些中小企業(yè)奕剃,以低成本實(shí)現(xiàn)自己的軟件需求衷旅。
什么是多租戶技術(shù)
多租戶技術(shù)或稱多重租賃技術(shù),是一種軟件架構(gòu)技術(shù)纵朋,是實(shí)現(xiàn)如何在多用戶環(huán)境下(此處的多用戶一般是面向企業(yè))共用相同的系統(tǒng)或程序組件柿顶,并且確保各用戶間數(shù)據(jù)隔離性。
在一臺服務(wù)器上運(yùn)行單個(gè)應(yīng)用實(shí)例操软,它為多個(gè)租戶(客戶)提供服務(wù)嘁锯。從定義中我們可以理解:多租戶是一種架構(gòu),目的是為了讓多用戶環(huán)境下使用同一套程序聂薪,且保證用戶間數(shù)據(jù)隔離家乘。多租戶的重點(diǎn)就是同程序下實(shí)現(xiàn)多用戶數(shù)據(jù)的隔離。
1.1什么是SaaS多租戶
SaaS藏澳,是Software-as-a-Service的縮寫名稱仁锯,意思為軟件即服務(wù),即通過網(wǎng)絡(luò)提供軟件服務(wù)翔悠。
SaaS平臺供應(yīng)商將應(yīng)用軟件統(tǒng)一部署在自己的服務(wù)器上业崖,客戶可以根據(jù)工作實(shí)際需求,通過互聯(lián)網(wǎng)向廠商訂購所需的應(yīng)用軟件服務(wù)蓄愁,按定購的服務(wù)多少和時(shí)間長短向廠商支付費(fèi)用双炕,并通過互聯(lián)網(wǎng)獲得SaaS平臺供應(yīng)商提供的服務(wù)。
SaaS服務(wù)通炒樽ィ基于一套標(biāo)準(zhǔn)軟件系統(tǒng)為成百上千的不同客戶(又稱為租戶)提供服務(wù)妇斤。這要求SaaS服務(wù)能夠支持不同租戶之間數(shù)據(jù)和配置的隔離,從而保證每個(gè)租戶數(shù)據(jù)的安全與隱私丹拯,以及用戶對諸如界面站超、業(yè)務(wù)邏輯、數(shù)據(jù)結(jié)構(gòu)等的個(gè)性化需求咽笼。由于SaaS同時(shí)支持多個(gè)租戶顷编,每個(gè)租戶又有很多用戶戚炫,這對支撐軟件的基礎(chǔ)設(shè)施平臺的性能剑刑、穩(wěn)定性和擴(kuò)展性提出很大挑戰(zhàn)。
多租戶是SaaS領(lǐng)域的特有產(chǎn)物,探究何為多租戶需回歸到對SaaS的理解上施掏。
SaaS服務(wù)是指部署在云上的钮惠,客戶可以按需購買,并通過網(wǎng)絡(luò)請求就能獲取到的服務(wù)七芭;也就是說素挽,在這樣的場景下,會有N個(gè)客戶同時(shí)使用同一套SaaS服務(wù)狸驳。
那么對SaaS服務(wù)供應(yīng)商來說预明,構(gòu)建SaaS體系需要完成兩部分工作:上層服務(wù)+底層多租戶系統(tǒng)。
上層服務(wù)是供應(yīng)商對外售賣的軟件服務(wù)耙箍,其可以為客戶創(chuàng)造價(jià)值撰糠、為公司帶來營收;而底層多租戶系統(tǒng)則是SaaS模式實(shí)現(xiàn)的具體方式辩昆,公司在對外售賣SaaS服務(wù)時(shí)阅酪,需要考慮如何實(shí)現(xiàn)客戶之間的數(shù)據(jù)隔離、服務(wù)的權(quán)限控制汁针、計(jì)費(fèi)管理等术辐;因此需要引入多租戶概念來解決上述問題。
通過多租戶系統(tǒng)施无,公司可以更好的管理客戶和上層服務(wù)辉词,客戶也可以更好的使用軟件服務(wù)。這也就是多租戶系統(tǒng)存在的意義了猾骡。
1.2 SaaS多租戶的優(yōu)勢
開發(fā)和運(yùn)維成本低
按需付費(fèi)较屿,節(jié)約成本
即租即用,軟件版本更新快
故障排查更及時(shí)
大數(shù)據(jù)和AI的能力支持更強(qiáng)大
1.3 多租戶模型
如圖所示卓练,涉及主要模型有以下幾類:
(1)租戶:指一個(gè)企業(yè)客戶或是個(gè)人客戶隘蝎,租戶之間數(shù)據(jù)與行為隔離,上下級租戶間通過授權(quán)實(shí)現(xiàn)數(shù)據(jù)共享襟企。每個(gè)租戶只能操作歸屬或授權(quán)給該租戶的數(shù)據(jù)嘱么;
(2)組織:如果租戶是一個(gè)企業(yè)客戶,通常就會擁有自己的組織架構(gòu)顽悼;
(3)用戶:租戶下的具體使用者曼振,擁有用戶名、密碼蔚龙、郵箱等賬號信息的自然人冰评;
(4)角色:用戶操作權(quán)限的集合;
(5)員工:組織內(nèi)的某位員工木羹;
(6)解決方案:為了解決客戶的某類型業(yè)務(wù)問題甲雅,SaaS供應(yīng)商一般都將產(chǎn)品和服務(wù)組合在一起解孙,為客戶提供整體的打包方案;
(7)產(chǎn)品能力:能夠幫助客戶實(shí)現(xiàn)場景解決方案閉環(huán)的能力抛人;
(8)資源域:用來運(yùn)行1個(gè)或多個(gè)產(chǎn)品應(yīng)用的一套云資源環(huán)境弛姜;
(9)云資源:SaaS產(chǎn)品一般都部署在各種云平臺上,例如阿里云妖枚、騰訊云廷臼、華為云等。對這些云平臺提供的計(jì)算绝页、存儲荠商、網(wǎng)絡(luò)、容器等資源续誉,抽象為云資源结啼。
二、SaaS多租戶的數(shù)據(jù)隔離設(shè)計(jì)方案
多租戶對于用戶來說屈芜,最主要的一點(diǎn)就在于數(shù)據(jù)隔離郊愧。
絕對不能出現(xiàn):一個(gè)用戶登了A用戶單位的號,但是看到了B用戶單位的數(shù)據(jù)井佑。因此属铁,多租戶的數(shù)據(jù)庫設(shè)計(jì)方案和代碼實(shí)現(xiàn)就相當(dāng)有必要考慮了。
目前開發(fā)者們普遍接受的SaaS多租戶設(shè)計(jì)方案躬翁,常見的大概就3種:即為每個(gè)租戶提供獨(dú)立的數(shù)據(jù)庫焦蘑、獨(dú)立的表空間、按字段區(qū)分租戶盒发,每種方案都有其各自的適用情況例嘱。
一個(gè)租戶獨(dú)立一個(gè)數(shù)據(jù)庫
一個(gè)租戶獨(dú)立使用一個(gè)數(shù)據(jù)庫,那就意味著我們的SaaS系統(tǒng)需要連接多個(gè)數(shù)據(jù)庫宁舰,這種實(shí)現(xiàn)方案其實(shí)就和分庫分表架構(gòu)設(shè)計(jì)是一樣的拼卵,好處就是數(shù)據(jù)隔離級別特別高、安全性好蛮艰,畢竟一個(gè)租戶單用一個(gè)數(shù)據(jù)庫腋腮,但是物理硬件成本,維護(hù)成本也變高了壤蚜。
獨(dú)立的表空間
這種方案的實(shí)現(xiàn)方式即寡,就是所有租戶共用一個(gè)數(shù)據(jù)庫系統(tǒng),但是每個(gè)租戶在數(shù)據(jù)庫系統(tǒng)中擁有一個(gè)獨(dú)立的表空間袜刷。
按租戶id字段隔離租戶
這種方案是多租戶方案中最簡單的數(shù)據(jù)隔離方案聪富,即在每張表中都添加一個(gè)用于區(qū)分租戶的字段(如tenant_id或org_id啥的)來標(biāo)識每條數(shù)據(jù)屬于哪個(gè)租戶,當(dāng)進(jìn)行查詢的時(shí)候每條語句都要添加該字段作為過濾條件著蟹,其特點(diǎn)是所有租戶的數(shù)據(jù)全都存放在同一個(gè)表中墩蔓,數(shù)據(jù)的隔離性是最低的梢莽,完全是通過字段來區(qū)分的,很容易把數(shù)據(jù)搞串或者誤操作钢拧。
2.1三種數(shù)據(jù)隔離架構(gòu)設(shè)計(jì)的對比
大部分公司都是采用第三種多租戶設(shè)計(jì)方案:按租戶id字段隔離租戶架構(gòu)設(shè)計(jì)實(shí)現(xiàn)多租戶數(shù)據(jù)隔離的。
因?yàn)檫@種方案服務(wù)器成本最低炕横,但是提高了開發(fā)成本源内。
2.2MyBatis-Plus多租戶插件優(yōu)雅實(shí)現(xiàn)數(shù)據(jù)隔離
該系統(tǒng)只有一個(gè)數(shù)據(jù)庫,所有租戶共用數(shù)據(jù)表份殿。
在每一個(gè)數(shù)據(jù)表中增加一列租戶ID膜钓,用以區(qū)分租戶的數(shù)據(jù)。
增刪改查時(shí)卿嘲,一定要帶上租戶ID颂斜,否則就會操作到其他租戶的數(shù)據(jù)。因此拾枣,這里的設(shè)計(jì)一定要重點(diǎn)考慮沃疮。
我們要保證的就是一定不要忘記帶上租戶ID。一個(gè)很好的方案就是通過AOP的方案梅肤,隱式的為我們的每一個(gè)SQL帶上這個(gè)租戶ID司蔬。
推薦使用MyBatis-Plus來操作數(shù)據(jù)庫的。它提供了插件的機(jī)制姨蝴,我們可以通過攔截它提供的四大組件的某些對象俊啼,某些方法,來操作SQL左医,動態(tài)的為我們的SQL拼接上租戶ID字段授帕。
當(dāng)然,MyBatis-Plus高版本提供了更加方便的攔截器浮梢,并且已經(jīng)將多租戶插件放入JAR包跛十,我們只需稍加實(shí)現(xiàn),并將該插件加入到MyBatis的攔截器鏈中秕硝,就可以不用再顯示的拼接租戶ID字段了偶器,降低了出錯(cuò)的概率。
三缝裤、MyBatisPlus實(shí)現(xiàn)多租戶功能
如果希望以最少的服務(wù)器為最多的租戶提供服務(wù)屏轰,并且租戶接受以犧牲隔離級別換取降低成本”锓桑可以采用方案三霎苗,即共享數(shù)據(jù)庫,共享數(shù)據(jù)架構(gòu)榛做,因?yàn)檫@種方案服務(wù)器成本最低唁盏,但是提高了開發(fā)成本内狸。
所以MyBatisPlus就提供了一種多租戶的解決方案,實(shí)現(xiàn)方式是基于多租戶插件TenantLinelnnerlnterceptor進(jìn)行實(shí)現(xiàn)的厘擂。
在MyBatis Plus中昆淡,采用“共享數(shù)據(jù)庫,共享數(shù)據(jù)架構(gòu)”方式實(shí)現(xiàn)多租戶刽严。
mybatisPlus提供了租戶處理器(Tenantld行級)昂灵,租戶之間共享數(shù)據(jù)庫,共享數(shù)據(jù)架構(gòu)舞萄,通過表字段(租戶ID)進(jìn)行數(shù)據(jù)邏輯隔離眨补。
該種實(shí)現(xiàn)方式,需要我們在要實(shí)現(xiàn)多租戶的表中添加tenant_id(租戶ID)字段倒脓,每次在對數(shù)據(jù)庫操作時(shí)都需要在where后面添加租戶判斷條件“tenant_id=用戶的租戶ID”撑螺。
然而,使用了MyBatis Plus后崎弃,我們就不需要每次都手動在where后面添加tenant_id條件甘晤。
注意事項(xiàng):
多租戶!=權(quán)限過濾饲做,不要亂用安皱,租戶之間時(shí)完全隔離的!Mа住酌伊!
啟用多租戶后所有執(zhí)行的method的sql都會進(jìn)行處理。
自寫的sql請按規(guī)范書寫(sql涉及到多個(gè)表的每個(gè)表都要給別名缀踪,特別是inner join的要寫標(biāo)準(zhǔn)的inner join)
<!-- Mybatis-Plus 增強(qiáng)CRUD -->
<dependency>
? ? <groupId>com.baomidou</groupId>
? ? <artifactId>mybatis-plus-boot-starter</artifactId>
? ? <version>3.5.1</version>
</dependency>
<!-- Mybatis-Plus 擴(kuò)展插件 -->
<dependency>
? ? <groupId>com.baomidou</groupId>
? ? <artifactId>mybatis-plus-extension</artifactId>
? ? <version>3.5.1</version>
</dependency>
TenantLineInnerInterceptor是MybatisPlus中提供的多租戶插件居砖,其使用方法大致分為下面4步:
3.1表及實(shí)體類添加租戶ID
應(yīng)用添加維護(hù)一張tenant(租戶表),記錄租戶的信息驴娃,每一個(gè)租戶奏候,有一個(gè)租戶ID。
然后唇敞,在需要進(jìn)行隔離的數(shù)據(jù)表上新增租戶id蔗草,例如,現(xiàn)在有數(shù)據(jù)庫表(user)如下:
租戶ID一般用tenant_id
將tenantId用來隔離租戶與租戶之間的數(shù)據(jù)疆柔,如果要查詢當(dāng)前服務(wù)商的用戶咒精,SQL大致如下:
SELECT * FROM table t WHERE t.tenantId = 1;
3.2application文件中添加多租戶配置和新增配置屬性類
(1)設(shè)置環(huán)境變量,配置攔截規(guī)則:
tenant.enable: 可以設(shè)置是否開啟多租戶旷档,
tenant.ignoreTables:需要進(jìn)行租戶id過濾的表名集合模叙。
tenant.filterTables:對多租戶的表設(shè)置白名單忽略多租戶攔截等。例如sys_user表結(jié)構(gòu)中鞋屈,沒有tenant_id多租戶字段范咨,那么多租戶攔截器不攔截該表故觅。
#多租戶配置
tenant:
? enable: true
? column: tenant_id
? filterTables:
? ignoreTables:
? ? - sys_app
? ? - sys_config
? ? - sys_dict_data
? ? - sys_dict_type
? ? - sys_logininfor
? ? - sys_menu
? ? - sys_notice
? ? - sys_oper_log
? ? - sys_role
? ? - sys_role_menu
? ? - sys_user
? ? - sys_user_role
? ignoreLoginNames:
(2)多租戶配置屬性類
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 多租戶配置屬性類
*
* @author hege
* @Date 2023-08-25
*
*/
@Data
@ConfigurationProperties(prefix = "tenant")
public class TenantProperties {
? ? /**
? ? * 是否開啟多租戶
? ? */
? ? private Boolean enable = true;
? ? /**
? ? * 租戶id字段名
? ? */
? ? private String column = "tenant_id";
? ? /**
? ? * 需要進(jìn)行租戶id過濾的表名集合
? ? */
? ? private List<String> filterTables;
? ? /**
? ? * 需要忽略的多租戶的表,此配置優(yōu)先filterTables渠啊,若此配置為空输吏,則啟用filterTables
? ? */
? ? private List<String> ignoreTables;
? ? /**
? ? * 需要排除租戶過濾的登錄用戶名
? ? */
? ? private List<String> ignoreLoginNames;
}
3.3編寫多租戶處理器實(shí)現(xiàn)TenantLineHandler接口
在 MyBatis Plus 中,提供了 TenantLineInnerInterceptor 插件和 TenantLineHandler 接口替蛉。
其中:
TenantLineInnerInterceptor 插件用來自動向每個(gè) SQL 的 where 后面添加判斷條件“tenant_id=用戶的租戶ID”贯溅。
而 TenantLineHandler 接口用來給 TenantLineInnerInterceptor 插件提供租戶ID、租戶字段名灭返。
TenantLineHandler 接口定義如下:
public interface TenantHandler {
? /**
? * 獲取租戶 ID 值表達(dá)式盗迟,支持多個(gè) ID 條件查詢
? * 支持自定義表達(dá)式坤邪,比如:tenant_id in (1,2) @since 2019-8-2
? * @param where 參數(shù) true 表示為 where 條件 false 表示為 insert 或者 select 條件
? * @return 租戶 ID 值表達(dá)式
? */
? Expression getTenantId(boolean where);
? /**
? * 獲取租戶字段名
? * @return 租戶字段名
? */
? String getTenantIdColumn();
? /**
? * 根據(jù)表名判斷是否進(jìn)行過濾
? * @param tableName 表名
? * @return 是否進(jìn)行過濾, true:表示忽略熙含,false:需要解析多租戶字段
? */
? boolean doTableFilter(String tableName);
}
實(shí)現(xiàn)TenantHandler接口并實(shí)現(xiàn)它的方法,下面是一個(gè)例子:
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.List;
/**
* 多租戶處理器實(shí)現(xiàn)TenantLineHandler接口
*
* @author hege
* @Date 2023-08-25
*/
public class MultiTenantHandler implements TenantLineHandler {
? ? private final TenantProperties properties;
? ? public MultiTenantHandler(TenantProperties properties) {
? ? ? ? this.properties = properties;
? ? }
? ? /**
? ? * 獲取租戶ID值表達(dá)式艇纺,只支持單個(gè)ID值 (實(shí)際應(yīng)該從用戶信息中獲取)
? ? *
? ? * @return 租戶ID值表達(dá)式
? ? */
? ? @Override
? ? public Expression getTenantId() {
? ? ? ? //實(shí)際應(yīng)該從用戶信息中獲取
? ? ? ? if(SecurityUtils.getTenantLoginUser()!=null)
? ? ? ? {
? ? ? ? ? ? //SecurityUtils 從ThreadLocal里面的安全上下文 中獲取 用戶所歸屬的單位id(租戶id)
? ? ? ? ? ? Long tenantId = SecurityUtils.getLoginUser().getUser().getRootPartyId();
? ? ? ? ? ? if(tenantId!=null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return new LongValue(tenantId);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return new LongValue(0);
? ? }
? ? /**
? ? * 獲取租戶字段名,默認(rèn)字段名叫: tenant_id
? ? *
? ? * @return 租戶字段名
? ? */
? ? @Override
? ? public String getTenantIdColumn() {
? ? ? ? //通過配置獲取
? ? ? ? return properties.getColumn();
? ? }
? ? /**
? ? * 根據(jù)表名判斷是否忽略拼接多租戶條件
? ? *
? ? * 默認(rèn)都要進(jìn)行解析并拼接多租戶條件
? ? *
? ? * @param tableName 表名
? ? * @return 是否忽略, true:表示忽略怎静,false:需要解析并拼接多租戶條件
? ? */
? ? @Override
? ? public boolean ignoreTable(String tableName) {
? ? ? ? //忽略指定用戶對租戶的數(shù)據(jù)過濾
? ? ? ? List<String> ignoreLoginNames=properties.getIgnoreLoginNames();
? ? ? ? //SecurityUtils 從ThreadLocal里面的安全上下文 中獲取 用戶名稱
? ? ? ? String loginName=SecurityUtils.getTenantUsername();
? ? ? ? if(null!=ignoreLoginNames && ignoreLoginNames.contains(loginName)){
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? //忽略指定表對租戶數(shù)據(jù)的過濾
? ? ? ? List<String> ignoreTables = properties.getIgnoreTables();
? ? ? ? if (null != ignoreTables && ignoreTables.contains(tableName)) {
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? return false;
? ? }
}
SecurityUtils 從ThreadLocal里面的安全上下文 中獲取 用戶名稱, 用戶所歸屬的單位id(租戶id)
3.4MybatisPlus配置類啟用多租戶攔截插件運(yùn)行sql實(shí)例:
前面講到黔衡,在 MyBatis Plus 中蚓聘,提供了 TenantLineInnerInterceptor 插件和 TenantLineHandler 接口。
其中盟劫,TenantLineInnerInterceptor 插件用來自動向每個(gè) SQL 的 where 后面添加判斷條件“tenant_id=用戶的租戶ID”夜牡。
TenantLineInnerInterceptor 插件 調(diào)用 TenantLineHandler 接口用來給 提供租戶ID、租戶字段名侣签。
使用 @Configuration 和 @Bean 注解配置 MyBatis Plus 的多租戶插件塘装,
iimport com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Mybatis Plus 配置
*
* @author hege
*/
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
@EnableConfigurationProperties(TenantProperties.class)
public class MybatisPlusConfig {
? ? /**
? ? * 如果用了分頁插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
? ? *
? ? * @param tenantProperties
? ? * @return
? ? */
? ? @Bean
? ? public MybatisPlusInterceptor mybatisPlusInterceptor(TenantProperties tenantProperties) {
? ? ? ? MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
? ? ? ? if (Boolean.TRUE.equals(tenantProperties.getEnable())) {
? ? ? ? ? ? // 啟用多租戶插件攔截
? ? ? ? ? ? interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new MultiTenantHandler(tenantProperties)));
? ? ? ? }
? ? ? ? // 分頁插件
? ? ? ? interceptor.addInnerInterceptor(paginationInnerInterceptor());
? ? ? ? // 樂觀鎖插件
? ? ? ? interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
? ? ? ? // 阻斷插件
? ? ? ? interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
? ? ? ? return interceptor;
? ? }
}
配置好之后,不管是查詢影所、新增蹦肴、修改刪除方法,MP都會自動加上租戶ID的標(biāo)識猴娩,測試如下:
@Test
public void select(){
? List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery().eq(User::getAge, 18));
? users.forEach(System.out::println);
}
運(yùn)行sql實(shí)例:
DEBUG==> Preparing: SELECT id, login_name, name, password,
? ? ? email, salt, sex, age, phone, user_type, status,
? ? organization_id, create_time, update_time, version,
? ? tenant_id FROM sys_user
? WHERE sys_user.tenant_id = '001' AND is_delete = '0' AND age = ?
驗(yàn)證結(jié)果:
針對MybatisPlus提供的API阴幌、自定義Mapper中的statement均可正常攔截,會在SQL執(zhí)行增刪改查的時(shí)候自動加上tenant_id卷中。
3.5特定SQL語句忽略攔截
如果在程序中矛双,有部分SQL不需要加上租戶ID的表示,需要過濾特定的sql蟆豫,或者對于一些超級管理員使用的接口背零,希望跨租戶查詢、免數(shù)據(jù)鑒權(quán)時(shí)无埃,無需多租戶攔截徙瓶。
怎么辦毛雇?
可以通過下面幾種方式實(shí)現(xiàn)忽略攔截:
方法1:使用MybatisPlus框架自帶的@InterceptorIgnore注解,以用在Mapper類上侦镇,也可以用在方法上
方法2:添加超級用戶賬號白名單灵疮,在自定義的Handler里進(jìn)行邏輯判斷,跳過攔截
方法3:添加數(shù)據(jù)表白名單壳繁,在自定義的Handler里進(jìn)行邏輯判斷震捣,跳過攔截
使用MybatisPlus框架自帶的@InterceptorIgnore注解,以用在Mapper類上闹炉,也可以用在方法上蒿赢, 下面是一個(gè)例子:
/**
* 使用@InterceptorIgnore注解,忽略多租戶攔截 <br/>
* 注解@InterceptorIgnore可以用在Mapper類上渣触,也可以用在方法上
*
* @param id
* @return
*/
@InterceptorIgnore(tenantLine = "true")
UserOrgVO myFindByIdNoTenant(@Param(value = "id") Long id);
參考文獻(xiàn)
https://mp.weixin.qq.com/s/TR75wnxsXgFZ2ot1dOvX2w
https://mp.weixin.qq.com/s/CVTuEINWHCLue1oB7Yr3ng
https://mp.weixin.qq.com/s/Nl5Oll9GcF6JB8JvIb2YqA
https://zhuanlan.zhihu.com/p/420696556
https://blog.csdn.net/CSDN2497242041/article/details/132525117
原文鏈接:https://blog.csdn.net/qq_45038038/article/details/135575700