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 …...

JS-Web API -day06
一、正则表达式 正则表达式测试工具: http://tool.oschina.net/regex 1.1 正则表达式介绍与语法 正则表达式: 正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。通常用来查…...

JS-Web API -day03
一、事件流 1.1 事件流与两个阶段说明 事件流 指的是事件完整执行过程中的流动路径 假设页面有个div标签,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段 捕获阶段:Document - Element html - Elementbody - Element div…...

进程优先级
基本概念 cpu资源分配的先后顺序,就是指进程的优先权(priority)。 优先权⾼的进程有优先执⾏权利。配置进程优先权对多任务环境的linux很有⽤,可以改善系统性能;还可以把进程运⾏到指定的CPU上,这样⼀来&…...

c语言(转义字符)
前言: 内容: 然后记一下转义字符 \? 在书写连续多个问号时使用,防止他们被解析成三字母词 \ 用于表示字符常量 \\ 用于表示一个反斜杠,防止他被解析为一个转义序列符 \n 换行 \r …...

easyexcel读取写入excel easyexceldemo
1.新建springboot项目 2.添加pom依赖 <name>excel</name> <description>excelspringboot例子</description><parent> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId&…...

【人工智能数学基础篇】——深入详解矩阵分解:奇异值分解(SVD)与主成分分析(PCA)在数据降维与特征提取中的应用
目录 1. 引言 2. 矩阵分解概述 2.1 矩阵分解的意义 3. 奇异值分解(SVD) 3.1 定义与数学基础 3.2 SVD 的性质 3.3 SVD 在数据降维中的应用 3.4 示例代码:使用 SVD 进行图像压缩 3.5 结果分析 4. 主成分分析(PCA࿰…...

ThreeJS示例教程200+【目录】
Three.js 是一个强大的 JavaScript 库,旨在简化在网页上创建和展示3D图形的过程。它基于 WebGL 技术,但提供了比直接使用 WebGL 更易于使用的API,使得开发者无需深入了解 WebGL 的复杂细节就能创建出高质量的3D内容。 由于目前内容还不多,下面的内容暂时做一个占位。 文章目…...

DC-DC稳压电源——实战(基于Ti5450芯片)基础知识篇(1)
一:基础知识-耦合 1)去耦电容 (1)耦合与去耦 耦合:系统内部的各个部分之间存在相互依赖、相互影响、相互制约的情况。用人话说就是不同部分之间的相互影响。 去耦:自然就是消除不同部分之间的影响了。 &…...

pyrender 渲染mesh
目录 render_meshes函数 调用函数 render_meshes函数 def overlay_human_meshes(humans, K, model, img_pil, unique_colorFalse):# Color of humans seen in the image._color [color[0] for _ in range(len(humans))] if unique_color else color# Get focal and princpt …...

防火墙安全策略
目录 一.拓扑信息 二.需求分析 三.命令行详细配置信息 1.配置IP 2.交换机配置 3.修改安全区域 4.安全策略 四.web界面详细配置 1.配置IP和设置安全区域 2.交换机配置 3.安全策略 五.测试 一.拓扑信息 二.需求分析 1.VLAN 2属于办公区域;VLAN 3属于生…...