mysql-plus 動態修改全局sql, 進行數據隔離, 多租戶, 多字段修改

需求:

1, 不同的權限角色看見的數據不一樣, 進行數據隔離

2, 大部分表裏面都維護了一個sys_code 大區編號,   1 是湖南, 2 是廣東, 他們需要看到數據是不一樣的

3, 不需要每個查詢都自己去判斷角色去修改sql,   可以配置多個字段, sys_code 隔離,  city_id 隔離, 省管理, 和市管理, 靈活配置

package com.test.first;

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.core.parser.ISqlParserFilter;
import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

@Configuration
@MapperScan(basePackages = {"com.dao"})
public class FilterConfig {
    private static final Map<String, String > IGNORE_TENANT_SMAP = new HashMap<String, String>(){{
        // 這些mapper 方法也不修改
        put("com.test.first.dao.TestMapper.getId","");
        put("com.test.first.dao.TestMapper.getId2","");
        put("com.test.first.dao.TestMapper.getId3","");
    }};

    private static final HashSet<String> TABLE_FILTER = new HashSet();

    static {
        // 過濾表, 這些表不進行修改
        TABLE_FILTER.add("sys_user");
        TABLE_FILTER.add("sys_user1");
        TABLE_FILTER.add("sys_user2");
    }

    @Autowired//自動注入request
    private HttpServletRequest request;

    @Bean
    @SuppressWarnings("all")
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        // sql 解析器
        List<ISqlParser> sqlParserList = new ArrayList<>();
        TenantSqlParser tenantSqlParser = new TenantSqlParser();
        tenantSqlParser.setTenantHandler(new TenantHandler() {
            @Override
            public Expression getTenantId() {
                HttpSession session = request.getSession();
                // 此處返回sys_code 字段值, 修改sql時候的參數, 從session 裏面獲取用戶,
                // 或者其他方式獲取用戶標識, 這裏方便直接寫死了
                return new LongValue(11);
            }
            @Override
            public String getTenantIdColumn() {
                // 返回增加條件的字段
                return "sys_code";
            }

            @Override
            public boolean doTableFilter(String tableName) {
                // 這裏可以判斷是否過濾表
                // 對沒有sys_code 的表格進行過濾
                if (TABLE_FILTER.contains(tableName)){
                    // 返回true 則不過濾
                    return true;
                }
                return false;
            }
        });


        // 添加到解析器, 如需添加多個, 這個地方是list, 多new幾個, new TenantSqlParser(); 即可
        sqlParserList.add(tenantSqlParser);

        // 設置解析器集合
        paginationInterceptor.setSqlParserList(sqlParserList);

        // 過濾函數
        paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
            @Override
            public boolean doFilter(MetaObject metaObject) {
                MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);
                // com.test.first.dao.TestMapper.getId 精確到mapper 方法級
                if(IGNORE_TENANT_SMAP.containsKey(ms.getId())) {
                    // 不進行修改
                    return true;
                }
                return false;
            }
        });
        return paginationInterceptor;
    }
}

原始sql

SELECT * FROM bd_product

經過配置後會自動增加條件

SELECT * FROM bd_product WHERE sys_code = 11

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章