1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        使用MyBatisPlus實(shí)現(xiàn)多租戶功能

        共 6998字,需瀏覽 14分鐘

         ·

        2022-08-03 13:29


        來源:blog.csdn.net/weixin_38111957/

        article/details/101161660

        • 一、引言
        • 二、具體實(shí)現(xiàn)
        • 三、特定SQL過濾

        一、引言

        我先解釋一下什么叫多租戶,什么場景下使用多租戶。

        多租戶是一種軟件架構(gòu)技術(shù),在多用戶的環(huán)境下,共有同一套系統(tǒng),并且要注意數(shù)據(jù)之間的隔離性。

        舉個實(shí)際例子:小編曾經(jīng)開發(fā)過一套H5程序,這套程序應(yīng)用在不同醫(yī)院的APP上,當(dāng)醫(yī)院患者下載醫(yī)院APP,并且進(jìn)入相對應(yīng)的H5頁面,APP則會把用戶相關(guān)數(shù)據(jù)傳輸?shù)叫【庍@里。在傳輸?shù)臅r候需要帶上醫(yī)院標(biāo)識(租戶ID),以便小編將數(shù)據(jù)進(jìn)行隔離。

        當(dāng)不同的租戶使用同一套程序,這里就需要考慮一個數(shù)據(jù)隔離的情況。

        數(shù)據(jù)隔離有三種方案:

        1. 獨(dú)立數(shù)據(jù)庫:簡單來說就是一個租戶使用一個數(shù)據(jù)庫,這種數(shù)據(jù)隔離級別最高,安全性最好,但是提高成本。
        2. 共享數(shù)據(jù)庫、隔離數(shù)據(jù)架構(gòu):多租戶使用同一個數(shù)據(jù)褲,但是每個租戶對應(yīng)一個Schema(數(shù)據(jù)庫user)。
        3. 共享數(shù)據(jù)庫、共享數(shù)據(jù)架構(gòu):使用同一個數(shù)據(jù)庫,同一個Schema,但是在表中增加了租戶ID的字段,這種共享數(shù)據(jù)程度最高,隔離級別最低。

        二、具體實(shí)現(xiàn)

        這里采用方案三,即共享數(shù)據(jù)庫,共享數(shù)據(jù)架構(gòu),因?yàn)檫@種方案服務(wù)器成本最低,但是提高了開發(fā)成本。

        所以MP就提供了一種多租戶的解決方案,實(shí)現(xiàn)方式是基于分頁插件進(jìn)行實(shí)現(xiàn)的,具體實(shí)現(xiàn)代碼如下:

        @Configuration
        public class MyBatisPlusConfig {
            /**
             * 分頁插件
             *
             * @return
             */

            @Bean
            public PaginationInterceptor paginationInterceptor() {
                PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

                // 創(chuàng)建SQL解析器集合
                List<ISqlParser> sqlParserList = new ArrayList<>();

                // 創(chuàng)建租戶SQL解析器
                TenantSqlParser tenantSqlParser = new TenantSqlParser();

                // 設(shè)置租戶處理器
                tenantSqlParser.setTenantHandler(new TenantHandler() {
                    @Override
                    public Expression getTenantId() {
                        // 設(shè)置當(dāng)前租戶ID,實(shí)際情況你可以從cookie、或者緩存中拿都行
                        return new StringValue("jiannan");
                    }

                    @Override
                    public String getTenantIdColumn() {
                        // 對應(yīng)數(shù)據(jù)庫租戶ID的列名
                        return "tenant_id";
                    }

                    @Override
                    public boolean doTableFilter(String tableName) {
                        // 是否需要需要過濾某一張表
                      /*  List<String> tableNameList = Arrays.asList("sys_user");
                        if (tableNameList.contains(tableName)){
                            return true;
                        }*/

                        return false;
                    }
                });

                sqlParserList.add(tenantSqlParser);
                paginationInterceptor.setSqlParserList(sqlParserList);

                return paginationInterceptor;
            }
        }

        配置好之后,不管是查詢、新增、修改刪除方法,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);
        }
        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 = 'jiannan' AND is_delete = '0' AND age = ? 
        DEBUG==> Parameters: 18(Integer)
        DEBUG<==      Total: 0

        三、特定SQL過濾

        如果在程序中,有部分SQL不需要加上租戶ID的表示,需要過濾特定的sql,可以通過如下兩種方式:

        方式一:在配置分頁插件中加上配置ISqlParserFilter解析器,如果配置SQL很多,比較麻煩,不建議。

        paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
            @Override
            public boolean doFilter(MetaObject metaObject) {
                MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);
                // 對應(yīng)Mapper、dao中的方法
                if("com.example.demo.mapper.UserMapper.selectList".equals(ms.getId())){
                    return true;
                }
                return false;
            }
        });

        方式二:通過租戶注解的形式,目前只能作用于Mapper的方法上。

        /**
         * 用戶 Mapper 接口
         */

        public interface UserMapper extends BaseMapper<User{

            /**
             * 自定Wrapper修改
             *
             * @param userWrapper 條件構(gòu)造器
             * @param user        修改的對象參數(shù)
             * @return
             */

            @SqlParser(filter = true)
            int updateByMyWrapper(@Param(Constants.WRAPPER) Wrapper<User> userWrapper, @Param("user") User user);

        }
        # 開啟 SQL 解析緩存注解生效,如果你的MP版本在3.1.1及以上則不需要配置
        mybatis-plus:
          global-config:
            sql-parser-cache: true

        現(xiàn)在各大廠內(nèi)卷的非常厲害,基于 2b 的 saas 系統(tǒng)正在蓬勃發(fā)展,多學(xué)一些這方面的經(jīng)驗(yàn),對職業(yè)發(fā)展多少有些幫助!本文就講到這里,感謝大家閱讀!

        程序汪資料鏈接

        程序汪接的7個私活都在這里,經(jīng)驗(yàn)整理

        Java項(xiàng)目分享  最新整理全集,找項(xiàng)目不累啦 07版

        堪稱神級的Spring Boot手冊,從基礎(chǔ)入門到實(shí)戰(zhàn)進(jìn)階

        臥槽!字節(jié)跳動《算法中文手冊》火了,完整版 PDF 開放下載!

        臥槽!阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開放下載!

        字節(jié)跳動總結(jié)的設(shè)計(jì)模式 PDF 火了,完整版開放下載!


        歡迎添加程序汪個人微信 itwang009  進(jìn)粉絲群或圍觀朋友圈

        瀏覽 67
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美操 | 免费日逼| 欧美黄片免费 | 处女一级片 | 五月亚洲综合 | 美女被帅哥艹 | 男女激情福利 | 天天射天天操天天 | 国产高清在线a视频大全 | 欧美性感操逼 |