首页 > 其他分享 >自定义mybatis插件之全局数据过滤

自定义mybatis插件之全局数据过滤

时间:2023-05-05 22:23:30浏览次数:48  
标签:插件 table1 return 自定义 t1 public sql mybatis id

目录

一、介绍

通过开发mybatis的插件来实现对全局的sql查询语句进行拦截,并新增全局的过滤条件做到无感知的数据过滤,比如全局过滤某个租户的数据。

二、实现

  • 实现思路

    1、通过mybatis的拦截器拦截所有查询的sql

    2、使用Druid里面的工具类解析sql结构树

    3、通过各种递归遍历sql结构树获取所有表名和别名,包含子查询、with语句等等

    4、根据表名的黑名单和白名单判断是否需要增加过滤条件sql

    5、替换成新的sql

    6、执行sql获取新的结果集

  • 创建mybatis-plugin类GlobalConditionFilterPlugin.java

    @Intercepts({
            @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
    })
    public class GlobalConditionFilterPlugin implements Interceptor {
        private static final Logger log = LoggerFactory.getLogger(GlobalConditionFilterPlugin.class);
        private GlobalConditionFilterHandler globalConditionFilterHandler;
    
        public GlobalConditionFilterPlugin(GlobalConditionFilterHandler globalConditionFilterHandler) {
            this.globalConditionFilterHandler = globalConditionFilterHandler;
        }
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            Object[] args = invocation.getArgs();
    
            MappedStatement mappedStatement = (MappedStatement) args[0];
            Object parameter = args[1];
            BoundSql originBoundSql = mappedStatement.getBoundSql(parameter);
    
            // 获取原始sql
            String sql = originBoundSql.getSql();
            log.info("原始sql:\n{}", sql);
    
            // 添加过滤条件转换新的sql
            DruidSql druidSql = new DruidSql(sql, JdbcConstants.MYSQL);
            druidSql.appendFilterCondition(
                    new WhereConditionAppender(
                            globalConditionFilterHandler.getColumn(),
                            globalConditionFilterHandler.getColumnValue(),
                            (tableName) -> globalConditionFilterHandler.support(tableName)
                    )
            );
            sql = druidSql.getSql();
            log.info("转换sql:\n{}", sql);
    
            MappedStatement newMappedStatement = MybatisPluginHelper.newMappedStatement(
                    mappedStatement,
                    MybatisPluginHelper.newBoundSql(mappedStatement, originBoundSql, sql)
            );
            args[0] = newMappedStatement;
            return invocation.proceed();
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
        }
    }
    
  • 定义mybatis的拦截器bean

    	@Bean
        public Interceptor[] interceptors() {
            return new Interceptor[]{globalConditionFilterPlugin()};
        }
    
        private GlobalConditionFilterPlugin globalConditionFilterPlugin() {
            return new GlobalConditionFilterPlugin(new GlobalConditionFilterHandler() {
                @Override
                public String getColumn() {
                    return "project_id";
                }
    
                @Override
                public Object getColumnValue() {
                    return 1L;
                }
    
                @Override
                public String[] getIncludeTable() {
                    return new String[]{"t_table1", "t_table3"};
                }
    
                @Override
                public String[] getExcludeTable() {
                    return new String[0];
                }
            });
        }
    
  • 完整代码见【四、源码】

三、效果

以下将展示通过插件改变前后的sql,如有特殊sql并且当前不符合的可以联系我。

原始sql 转换后sql
select t1.*
from t_table1 as t1 join t_table2 as t2 on t1.id=t2.id
WHERE t1.id=1
order by t1.id asc
limit 10
SELECT t1.*
FROM t_table1 t1
JOIN t_table2 t2 ON t1.id = t2.id
WHERE t1.id = 1
AND t1.project_id = 1
ORDER BY t1.id ASC
LIMIT 10
select t1.*
from (select * from t_table1) as t1 join t_table2 as t2 on t1.id=t2.id
WHERE t1.id in (
select id
from t_table3
)
SELECT t1.*
FROM (
SELECT *
FROM t_table1
WHERE t_table1.project_id = 1
) t1
JOIN t_table2 t2 ON t1.id = t2.id
WHERE t1.id IN (
SELECT id
FROM t_table3
WHERE t_table3.project_id = 1
)
with table_4 as (
select *
from t_table1
)
select *
from table_4
WITH table_4 AS (
SELECT *
FROM t_table1
WHERE t_table1.project_id = 1
)
SELECT *
FROM table_4
select *
from t_table1
union all
select *
from t_table2
union all
select *
from t_table3
SELECT *
FROM t_table1
WHERE t_table1.project_id = 1
UNION ALL
SELECT *
FROM t_table2
UNION ALL
SELECT *
FROM t_table3
WHERE t_table3.project_id = 1

四、源码

https://github.com/1277463718lmt/mybatis-plugins.git

标签:插件,table1,return,自定义,t1,public,sql,mybatis,id
From: https://www.cnblogs.com/linmt/p/17375530.html

相关文章

  • MyBatis 配置详解
    目录mybatis-config.xml核心配置文件1.environments元素1.1子元素environment1.2transactionManager事务管理器(共两种)2.mappers元素(定义映射SQL语句文件)3.properties4.typeAliases(定义别名)其他配置【设置】mybatis-config.xml核心配置文件mybatis-config.xml包含的......
  • NSIS官方认证插件集成安装包
     本次制作的集成安装包集成了NSIS官方wiki认证的所有插件(无法下载或者严重过时的除外),翻译了部分比较冷门插件的使用说明。额外集成了关于皮肤,按钮美化以及用于窗口子类化等少数几个优秀的第三方插件。所有插件皆为当前能得到的最新版本。由于兼容性原因,在不干扰正常使用的情况下......
  • Eclipse4.5Mars安装JAD反编译插件
    第一步:打开eclipse帮助中的软件安装第二步:添加站点:http://feeling.sourceforge.net/update,如下图:第三步:选择EclipseClassDecompiler,下一步,下一步第四步:接受许可,安装!图略!第五步:重启eclipse!第六步:配置Jad,下图为EclipseClassDecompiler的首选项页面,可以选择缺省的反编译器工具,并......
  • Spring整合Mybatis
    1、Spring整合Mybatis思路分析1.1、环境准备在准备环境的过程中,我们也来回顾下Mybatis开发的相关内容:步骤1:准备数据库表Mybatis是来操作数据库表,所以先创建一个数据库及表createdatabasespring_dbcharactersetutf8;usespring_db;createtabletbl_account(id......
  • 轻量级插件框架x3py
    1、x3py用途1)x3py作为一个轻量级的C++插件框架,面向C++开发人员,首要目标是能快速容易的开发出中小型的软件、软件以插件形式模块化设计。其插件既可灵活组合到各个系统,又能单独拆开使用和测试。2)x3py可在Win/Linux/MacOS等平台上编译运行,可使用VS或GCC编译,具备基本的跨平台兼容......
  • vue 分页demo || vue分页插件
    方法一查看源码demo:点击预览方法二运用插件演示地址:点击预览查看源码:点击查阅......
  • 微信小程序-根据同声传译插件创建语音转文字的自定义插件
    使用了vantweapp组件.js//page/common/components/voice/voice.jsimportToastfrom'../../../../vant-weapp/dist/toast/toast';//引入插件:微信同声传译varplugin=requirePlugin("WechatVoice");//获取全局唯一的语音识别管理器recordRecoManagerletmanager=pl......
  • 谷歌浏览器chrome安装postman插件
    1获取postman插件压缩包链接:https://pan.baidu.com/s/1pCNJxrM4gCvODa9tIbteDg?pwd=waje提取码:waje  2安装2.1下载压缩包,并且解压,然后打开浏览器2.2点击浏览器右上角三个点,更多工具,扩展程序2.3打开开发者模式2.4点击加载扩展程序,选择解压后的文件po......
  • 到底什么是小程序插件?
    最近和小伙伴交流,时常发生插件、组件、控件等概念混淆的情况,因此导致经常会错意。感觉还是很有必要带大家整理清楚的,今天就来跟大家来聊一聊插件、组件、控件的区别。什么是插件先按照官方的一些解释来看看插件的概念描述?微信小程序官方描述:插件,是可被添加到小程序内直接使用......
  • Vue3 开发必备的 VSCode 插件
    分享6个Vue3开发必备的VSCode插件,可以直接用过VSCode的插件中心直接安装使用。1、Volar相信使用VSCode开发Vue2的同学一定对Vetur插件不会陌生,作为Vue2配套的VSCode插件,它的主要作用是对Vue单文件组件提供高亮、语法支持以及语法检测。而随着Vue3正式......