MyBatis Plus 的 InnerInterceptor:更轻量级的 SQL 拦截器
在 Spring Boot 项目中使用 MyBatis Plus 时,你可能会遇到 InnerInterceptor 这个概念。 InnerInterceptor 是 MyBatis Plus 提供的一种轻量级 SQL 拦截器,它与传统的 MyBatis 拦截器(Interceptor)有所不同,具有更简单、更高效的特点,并且更专注于 SQL 执行层面的拦截。本文将详细介绍 InnerInterceptor 的原理、用法和最佳实践,并提供代码示例。
一、为什么需要 InnerInterceptor?
- 更轻量级: 相比于传统的 Interceptor,InnerInterceptor 更加轻量级,减少了不必要的拦截开销,提高了性能。
- 更专注于 SQL 执行: InnerInterceptor 专注于 SQL 执行层面,可以让你更方便地修改 SQL 语句、参数或结果。
- 简化配置: InnerInterceptor 的配置更加简单,无需手动注册,MyBatis Plus 会自动识别并注册。
- 易于扩展:你可以通过实现 InnerInterceptor 接口,自定义 SQL 拦截逻辑。
- 与 MyBatis Plus 无缝集成:InnerInterceptor 与 MyBatis Plus 的其他功能无缝集成,可以更好地发挥 MyBatis Plus 的优势。
- 内置丰富功能: MyBatis Plus 提供了许多内置的 InnerInterceptor 实现,如分页插件、乐观锁插件、SQL性能分析插件等,可以直接使用。
二、InnerInterceptor 与 Interceptor 的区别
- 拦截范围:
Interceptor可以拦截 MyBatis 的 Executor、ParameterHandler、ResultSetHandler 和 StatementHandler 等组件,拦截范围更广。
InnerInterceptor主要拦截 SQL 执行过程中的 StatementHandler,拦截范围更窄,但更专注于 SQL 执行。 - 执行时机:
Interceptor可以拦截 SQL 执行过程中的多个阶段,例如参数处理、SQL 预编译、结果处理等。
InnerInterceptor主要拦截 StatementHandler 的 prepare 和 query 方法,更专注于 SQL 语句的准备和执行阶段。 - 配置方式:
Interceptor需要在 MyBatis 配置文件或 Spring Bean 中手动注册。
InnerInterceptor通过 MyBatis Plus 提供的 MybatisPlusInterceptor 统一注册管理,无需手动注册。 - 代码复杂度:
Interceptor的代码相对复杂,需要处理 Invocation 对象,并手动调用 proceed 方法。
InnerInterceptor的代码更加简洁,只需要重写对应的方法。 - 性能:
Interceptor由于拦截范围更广,可能会带来一定的性能开销。
InnerInterceptor由于拦截范围更窄,性能更高。
三、InnerInterceptor 的核心方法
- void
beforePrepare(StatementHandler sh, Connection connection,Integer transactionTimeout): 在 SQL 语句预编译之前调用。 - void
beforeQuery(StatementHandler sh, Connection connection, Integer transactionTimeout): 在 SQL 语句执行之前调用。 - void
afterQuery(StatementHandler sh, Connection connection, Integer transactionTimeout, Object result): 在 SQL 查询执行后调用。 - void
beforeUpdate(StatementHandler sh, Connection connection, Integer transactionTimeout): 在执行 INSERT 或 UPDATE 语句之前调用。 - void
afterUpdate(StatementHandler sh, Connection connection, Integer transactionTimeout,Object result): 在执行 INSERT 或 UPDATE 语句之后调用。
四、实践:使用 InnerInterceptor 修改 SQL 语句
4.1 创建 InnerInterceptor 实现类:
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;import java.io.StringReader;
import java.sql.SQLException;@Component
@Slf4j
public class MyInnerInterceptor implements InnerInterceptor {@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {String sql = boundSql.getSql();try {PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);//sql处理String filterSql = addFilterCondition(sql);log.info("修改过后的sql:{}", filterSql);//修改sqlmpBs.sql(filterSql);} catch (Exception e) {log.warn("动态修改sql:{}异常", sql, e);throw new SQLException("添加数据权限异常");}}public String addFilterCondition(String originalSql) throws JSQLParserException {CCJSqlParserManager parserManager = new CCJSqlParserManager();Select select = (Select) parserManager.parse(new StringReader(originalSql));PlainSelect plain = (PlainSelect) select.getSelectBody();Expression where_expression = plain.getWhere();// 这里可以根据需要增加过滤条件if (where_expression == null) {plain.setWhere(CCJSqlParserUtil.parseCondExpression("age = 35"));}return plain.toString();}
}
4.2 配置 MybatisPlusInterceptor
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.extend.chk.interceptor.MyInnerInterceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;
import java.util.List;@Configuration
public class MyBatisPlusConfig {@Autowiredprivate List<SqlSessionFactory> sqlSessionFactoryList;@Autowiredprivate MyInnerInterceptor myInnerInterceptor;/*** 添加Mybatis拦截器* 主要是为了保证数据权限拦截器在分页插件拦截器之前执行sql的修改,如果不在这里手动添加的话,PageInterceptor会先执行* 先添加的拦截器后执行*/@PostConstructpublic void addMybatisInterceptor() {for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();//将数据权限拦截器添加到MybatisPlusInterceptor拦截器链MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(myInnerInterceptor);//先添加PageHelper分页插件拦截器,再添加MybatisPlusInterceptor拦截器//configuration.addInterceptor(new PageInterceptor());configuration.addInterceptor(mybatisPlusInterceptor);}}
}
4.3 使用 InnerInterceptor
现在,你执行任何 SQL 语句,都会被 InnerInterceptor 拦截,你可以看到 SQL 语句已经被修改。
修改过后的sql:SELECT count(0) FROM t_user_info WHERE age = 35
修改过后的sql:SELECT id, name, password, age, status, last_login_time, token, create_by, create_time, update_by, update_time, remark FROM t_user_info WHERE age = 35 LIMIT ?
五、内置拦截器
除了自定义拦截器外,MyBatis-Plus 还提供了多个内置拦截器,可以直接使用或作为参考来创建自己的拦截器。以下是几个常用的内置拦截器:
PaginationInterceptor:分页插件,支持多种数据库的分页查询。PerformanceAnalyzerInterceptor:性能分析插件,记录每条 SQL 的执行时间和影响行数。OptimisticLockerInterceptor:乐观锁插件,用于防止并发更新时的数据覆盖问题。BlockAttackInterceptor:阻止恶意攻击插件,防止批量删除或更新操作导致数据丢失。
六、常见应用场景
- SQL 日志记录:如上文所示,记录每次 SQL 执行的时间、参数及结果,便于调试和性能分析。
- 分页插件:动态地为查询语句添加分页条件,而无需修改原有的 Mapper 文件。
- SQL 性能监控:统计每条 SQL 的执行次数、平均耗时等指标,帮助识别潜在的性能瓶颈。
- 缓存实现:基于拦截器实现简单的查询结果缓存,减少不必要的数据库访问。
- 数据脱敏:在查询结果返回之前,对敏感字段进行加密或替换,确保数据安全。
- 权限控制:在 SQL 执行前检查用户权限,防止未经授权的操作。
七、最佳实践
- 按需选择拦截器: 根据实际需求选择合适的拦截器,如果需要修改 SQL 语句、参数或结果,可以使用 InnerInterceptor,如果需要拦截 MyBatis 的其他组件,可以使用 Interceptor。
- 细粒度控制: 可以根据 MappedStatement 的 ID 或 SQL 语句内容,细粒度控制 InnerInterceptor 的执行范围。
- 使用内置的 InnerInterceptor: MyBatis Plus 提供了许多内置的 InnerInterceptor 实现,如分页插件、乐观锁插件、SQL 性能分析插件等,可以直接使用,无需重复开发。
- 避免耗时操作: InnerInterceptor 会在 SQL 执行的关键节点执行,避免在其中执行耗时的操作,以免影响性能。
- 异常处理: 在 InnerInterceptor 方法中使用 try-catch 代码块处理可能抛出的异常,避免影响正常业务逻辑。
- 配置顺序: 如果存在多个 InnerInterceptor,Mybatis Plus 会根据 addInnerInterceptor 方法的调用顺序进行执行。
- 使用 MyBatis Plus 工具类: MyBatis Plus 提供了一些工具类,例如 PluginUtils,可以方便地访问和修改 SQL 语句、参数等信息。
相关文章:
MyBatis Plus 的 InnerInterceptor:更轻量级的 SQL 拦截器
在 Spring Boot 项目中使用 MyBatis Plus 时,你可能会遇到 InnerInterceptor 这个概念。 InnerInterceptor 是 MyBatis Plus 提供的一种轻量级 SQL 拦截器,它与传统的 MyBatis 拦截器(Interceptor)有所不同,具有更简单…...
Java复习第四天
一、代码题 1.相同的树 (1)题目 给你两棵二叉树的根节点p和q,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p[1,2,3],q[1,2,3] 输出:true示例 2: 输…...
docker 安装 mysql 详解
在平常的开发工作中,我们经常需要用到 mysql 数据库。那么在docker容器中,应该怎么安装mysql数据库呢。简单来说,第一步:拉取镜像;第二步:创建挂载目录并设置 my.conf;第三步:启动容…...
本地Ubuntu轻松部署高效性能监控平台SigNoz与远程使用教程
文章目录 前言1.关于SigNoz2.本地部署SigNoz3.SigNoz简单使用4. 安装内网穿透5.配置SigNoz公网地址6. 配置固定公网地址 前言 本文介绍如何在Ubuntu系统上使用 Docker 快速部署一款强大的应用性能监控工具SigNoz,并结合cpolar内网穿透工具轻松实现异地远程使用。 …...
防火墙的会话并发数、端口数量及其关系
防火墙的会话并发数、端口数量及其关系: 会话并发数:会话并发数,也称为并发连接数,是指防火墙能够同时处理的点对点连接的最大数目。这个参数直接影响到防火墙在高流量环境下的表现,特别是对于需要处理大量并发…...
随机变量的变量替换——归一化流和直方图规定化的数学基础
变量替换是一种在统计学和数学中广泛应用的技术,它通过定义新的变量来简化问题,使得原本复杂的随机变量变得更加容易分析。 变量替换的公式,用于将一个随机变量 X X X 的概率密度函数 f X f_X fX 转换为其经过函数 g g g 变换后的随机变…...
Java春招面试指南前言
在当今竞争激烈的就业市场中,对于即将踏入职场的Java开发者而言,春招是一次宝贵的机会。本博客专栏旨在为大家提供一份全面且实用的Java春招面试指南,助力大家顺利通过面试,开启职业生涯的新篇章。 无论你是初出茅庐的应届生&…...
【技术洞察】2024科技绘卷:浪潮、突破、未来
涌动与突破 2024年,科技的浪潮汹涌澎湃,人工智能、量子计算、脑机接口等前沿技术如同璀璨星辰,方便了大家的日常生活,也照亮了人类未来的道路。这一年,科技的突破与创新不断刷新着人们对未来的想象。那么回顾2024年的科…...
为AI聊天工具添加一个知识系统 之54 为事务处理 设计 基于DDD的一个 AI操作系统 来处理维度
本文要点 要点 Architecture程序 它被设计为一个双面神结构的控制器,它的两侧一侧编译执行另一侧 解释执行,自已则是一个 翻译器--通过提供两个不同取向之间 的 结构映射的显示器(带 图形用户接口GUI和命令行接口CLI 两种 接口)…...
【数据结构】二分查找
🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…...
读书笔记《网络是怎样连接的》
目录 第一章1.1 生成http请求消息输入网址URL解析URLURL中省略文件名的情况http的基本思路生成HTTP请求消息发送请求后收到响应 1.2 向DNS服务器查询Web服务器的IP地址IP地址的基本知识域名和IP地址并用的理由Socket库提供查询IP地址的功能通过解析器向 DNS 服务器发出查询解析…...
Java 设计模式一
Java 设计模式是软件开发中的一类解决方案,旨在解决常见的设计问题,提升代码的可维护性、可复用性和扩展性。它们通常基于一些经验和最佳实践,提供了解决问题的标准化方法。以下是常见的 Java 设计模式及其概述: 1. 创建型模式 (…...
SOME/IP服务接口
本系列文章将分享我在学习 SOME/IP 过程中积累的一些感悟,并结合 SOME/IP 的理论知识进行讲解。主要内容是对相关知识的梳理,并结合实际代码展示 SOME/IP 的使用,旨在自我复习并与大家交流。文中引用了一些例图,但由于未能找到原作…...
Java 生成 PDF 文档 如此简单
嘿,朋友!在 Java 里实现 PDF 文档生成那可真是个挺有意思的事儿,今儿个就来好好唠唠这个。咱有不少好用的库可以选择,下面就给你详细讲讲其中两个超实用的库,一个是 iText,另一个是 Apache PDFBox。 用 iTe…...
深入探究 YOLOv5:从优势到模型导出全方位解析
一、引言 在计算机视觉领域,目标检测是一项至关重要的任务,它在自动驾驶、安防监控、工业检测等众多领域都有着广泛的应用。而 YOLO(You Only Look Once)系列作为目标检测算法中的佼佼者,一直备受关注。其中ÿ…...
【PoCL】运行 LLVM 中 pass 优化过程详解
PoCL 项目中调用 LLVM 的 Pass 对编译过程的优化至关重要。本博文以PoCL 开源项目源码为例,详细说明【PoCL】运行 LLVM 中 pass 优化过程 目录 0. 个人简介 && 授权须知1. pocl_llvm_run_pocl_passes 函数作用2. 禁止 “小网格 small grid” 工作组(workGroup)特化的…...
如何将使用unsloth微调的模型部署到ollama?
目录 一、将模型保存为gguf格式 二、下载llama.cpp 三、生成 llama-quantize 可执行文件 四、使用llama-quantize 五、训练模型 六、将模型部署到ollama 一、将模型保存为gguf格式 在你的训练代码 trainer.train() 之后添加: model.save_pretrained_gguf(&q…...
【测试】UI自动化测试
长期更新,建议关注收藏点赞! 目录 概论WEB环境搭建Selenium APPAppium 概论 使用工具和代码执行用例。 什么样的项目需要自动化? 需要回归测试、自动化的功能模块需求变更不频繁、项目周期长(功能测试时长:UI自动化测…...
SSM开发(二) MyBatis两种SQL配置方式及其对比
目录 一、MyBatis两种SQL配置方式 二、使用XML映射文件配置SQL语句 三、使用注解配置SQL语句 四、两种方式对比 总结 1、注解 2、XML配置 五、MyBatis多数据源的两种配置方式 参考 一、MyBatis两种SQL配置方式 MyBatis 提供了两种方式来配置SQL语句:注解&a…...
【Redis】在ubuntu上安装Redis
文章目录 提权搜索软件包安装修改配置文件ip保护模式配置密码 重新启动服务器使用 redis 自带的客户端来连接服务器 提权 先切换到 root 用户,su 命令切换到 root. 搜索软件包 使用 apt 命令来搜索 redis 相关的软件包 apt search redis 安装 使用 apt 命令安装 redisapt …...
Manta发票应用字体定制终极指南:如何为专业发票添加完美排版效果
Manta发票应用字体定制终极指南:如何为专业发票添加完美排版效果 【免费下载链接】Manta 🎉 Flexible invoicing desktop app with beautiful & customizable templates. 项目地址: https://gitcode.com/gh_mirrors/ma/Manta 🎉 想…...
终极解决方案:让Mac通过Android USB网络共享高速上网的HoRNDIS驱动
终极解决方案:让Mac通过Android USB网络共享高速上网的HoRNDIS驱动 【免费下载链接】HoRNDIS Android USB tethering driver for Mac OS X 项目地址: https://gitcode.com/gh_mirrors/ho/HoRNDIS 还在为Mac无法直接使用Android手机的USB网络共享功能而烦恼吗…...
如何通过4个步骤让百度网盘下载速度提升30倍?
如何通过4个步骤让百度网盘下载速度提升30倍? 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘几十KB的下载速度而焦虑吗?百度网盘直链解…...
Boss-Key终极指南:3秒掌握职场隐私保护的秘密武器
Boss-Key终极指南:3秒掌握职场隐私保护的秘密武器 【免费下载链接】Boss-Key 老板来了?快用Boss-Key老板键一键隐藏静音当前窗口!上班摸鱼必备神器 项目地址: https://gitcode.com/gh_mirrors/bo/Boss-Key 在现代职场环境中࿰…...
谷歌Home应用与Gemini Live更新:AI赋能智能家居与新闻交互新体验
谷歌Home应用更新:让智能家居控制更自然本周谷歌对其Home应用进行更新,借助Gemini AI助手,让用户控制智能家居变得“更加自然和可靠”。更新后,用户能以更自然的方式描述需求,如描述灯光类型为“海洋的颜色”ÿ…...
避坑指南:UE5 VaRest插件处理JSON数组和嵌套对象的几个常见错误
UE5 VaRest插件处理JSON数组和嵌套对象的避坑指南 在UE5开发中,VaRest插件因其便捷的HTTP请求和JSON处理能力而广受欢迎。然而,当面对复杂的JSON数据结构时,许多开发者会遇到各种"坑"。本文将深入剖析VaRest在处理JSON数组和嵌套对…...
Pylance:重新定义Python开发体验的智能助手
Pylance:重新定义Python开发体验的智能助手 【免费下载链接】pylance-release Documentation and issues for Pylance 项目地址: https://gitcode.com/gh_mirrors/py/pylance-release 提升30%编码效率的10个实战技巧 还在为Python代码补全延迟烦恼ÿ…...
三步快速配置:极简二维码插件让你的浏览器变身智能跨设备助手
三步快速配置:极简二维码插件让你的浏览器变身智能跨设备助手 【免费下载链接】chrome-qrcode chrome-qrcode - 一个 Chrome 浏览器插件,可以生成当前 URL 或选中文本的二维码,或解码网页上的二维码。 项目地址: https://gitcode.com/gh_mi…...
5个必知技巧:用Greasy Fork用户脚本彻底改变你的浏览器体验 [特殊字符]
5个必知技巧:用Greasy Fork用户脚本彻底改变你的浏览器体验 🚀 【免费下载链接】greasyfork An online repository of user scripts. 项目地址: https://gitcode.com/gh_mirrors/gr/greasyfork 你是否曾经想过,为什么别人的浏览器总是…...
手机相册端侧文本搜图方案调研
手机相册端侧文本搜图方案调研 调研日期:2026-04-02(UTC) 目标场景:手机相册中存在大量图片,需要支持基于自然语言的本地搜图;希望模型与系统架构可在骁龙平台端侧执行,并具备后续接入 tag/caption 与 rerank 的可扩展性。 一、结论摘要 已有现成开源例子,最接近目标场…...
