Mr. Cappuccino的第56杯咖啡——Mybatis拦截器
Mybatis拦截器
- 概述
- 应用场景
- 项目结构
- 实现分页查询
- 其它拦截器的使用
概述
Mybatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用,通过织入拦截器,在不同节点修改一些执行过程中的关键属性,从而影响SQL的生成、执行和返回结果。
默认情况下,Mybatis支持四种对象拦截:
- Executor:拦截执行器的方法;
- ParameterHandler:拦截参数的处理;
- ResultSetHandler:拦截结果集的处理;
- StatementHandler:拦截Sql语法构建的处理;
执行顺序:Executor => StatementHandler => ParameterHandler => ResultSetHandler
注:本文代码基于《Mybatis一级缓存&二级缓存》中的“一级缓存(Spring整合Mybatis)”的代码进行调整。
应用场景
- 分页查询;
- 数据脱敏;
- 数据过滤;
- 监控Sql语句执行耗时;
项目结构

实现分页查询
StatementInterceptor.java
package com.mybatis.interceptor;import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;/*** @author honey* @date 2023-08-02 15:25:26*/
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
})
@Component
public class StatementInterceptor implements Interceptor {@Value("${mybatis.page-helper.rule}")private String rule;@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();MetaObject metaObject = SystemMetaObject.forObject(statementHandler);MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();// 判断sql语句的类型switch (sqlCommandType) {case SELECT:extendLimit(statementHandler);break;case INSERT:case UPDATE:case DELETE:case FLUSH:default:break;}log.info("【StatementInterceptor】方法拦截前执行");Object result = invocation.proceed();log.info("【StatementInterceptor】方法拦截后执行");return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}private void extendLimit(StatementHandler statementHandler) throws NoSuchFieldException, IllegalAccessException {// 获取原生sql语句BoundSql boundSql = statementHandler.getBoundSql();Class<? extends BoundSql> aClass = boundSql.getClass();// 使用反射机制修改原生sql语句Field sql = aClass.getDeclaredField("sql");sql.setAccessible(true);String oldSqlStr = boundSql.getSql();log.info("原生sql语句:{}", oldSqlStr);// 加上分页规则sql.set(boundSql, oldSqlStr + " " + rule);}
}
application.yml
mybatis:page-helper:rule: limit 2

其它拦截器的使用
ExecutorInterceptor.java
package com.mybatis.interceptor;import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;import java.util.Properties;/*** @author honey* @date 2023-08-02 18:11:28*/
@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
@Component
public class ExecutorInterceptor implements Interceptor {Properties properties;@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.info("【ExecutorInterceptor】方法拦截前执行");Object result = invocation.proceed();log.info("【ExecutorInterceptor】方法拦截后执行");return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {this.properties = properties;}
}
ParameterInterceptor.java
package com.mybatis.interceptor;import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;import java.sql.PreparedStatement;
import java.util.Properties;/*** @author honey* @date 2023-08-02 18:22:15*/
@Slf4j
@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})
})
@Component
public class ParameterInterceptor implements Interceptor {Properties properties;@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.info("【ParameterInterceptor】方法拦截前执行");Object result = invocation.proceed();log.info("【ParameterInterceptor】方法拦截后执行");return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {this.properties = properties;}
}
ResultSetInterceptor.java
package com.mybatis.interceptor;import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;import java.sql.Statement;
import java.util.Properties;/*** @author honey* @date 2023-08-02 18:24:00*/
@Slf4j
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
@Component
public class ResultSetInterceptor implements Interceptor {Properties properties;@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.info("【ResultSetInterceptor】方法拦截前执行");Object result = invocation.proceed();log.info("【ResultSetInterceptor】方法拦截后执行");return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {this.properties = properties;}
}

相关文章:
Mr. Cappuccino的第56杯咖啡——Mybatis拦截器
Mybatis拦截器 概述应用场景项目结构实现分页查询其它拦截器的使用 概述 Mybatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用,通过织入拦截器,在不同节点修改一些执行过程中的关键属性,从而影响SQL的生成、执行和返回结果…...
容器化安装环境EFK搭建
容器化安装环境 Docker中安装并启动ElasticSearch 前置配置 第一步:在宿主机上执行echo “net.ipv4.ip_forward1” >>/usr/lib/sysctl.d/00-system.conf 2.第二步:重启network和docker服务 [rootlocalhost /]# systemctl restart network &&…...
基于 Debian GNU/Linux 12 “书虫 “的Neptune 8.0 “Juna “来了
导读Neptune Linux 发行版背后的团队发布了 Neptune 8.0,作为这个基于 Debian 的 GNU/Linux 发行版的重大更新,它围绕最新的 KDE Plasma 桌面环境构建。 Neptune 8.0 被命名为 “Juna”,是在Neptune 7.5 发布 11 个月后发布的,也是…...
GDAL C++ API 学习之路 (4) Spatial Reference System篇 OGRSpatialReference类
class OGRSpatialReference #include <ogr_spatialref.h> OGRSpatialReference 是 GDAL/OGR 库中的一个重要类,用于管理和操作地理空间数据的空间参考系统(Spatial Reference System,SRS)。它提供了一系列功能&…...
RS232转Profinet网关rs232转网口需要如何设置
大家好,今天我要给大家带来一个很有意思的案例分享。你们猜猜,这回我们要用捷米的一款神奇的网关JM-RS485/232-PN做什么呢?没错,我们要把一台扫码枪设备通过这个RS232转PROFINET网关,接入到一台西门子S7-1200PLC的Prof…...
LaTex的下载与安装超详细windows版
1.LaTex的下载 (texlive下载TexStudio下载) (1)texlive下载: 这里清华镜像下载 (2)TexStudio下载: 点这里下载镜像 可以根据不同的系统选择不同的版本 2 .LaTex的安装 &#…...
MySQL | 存储过程快速入门
文章目录 一、概述1.1 MySQL存储过程和函数的概念1.2 优势和适用场景 二、存储过程基础2.1 存储过程与传统SQL查询的区别2.2 创建和调用存储过程创建存储过程调用存储过程 2.3 参数传递与返回值创建带有输出参数的存储过程调用带有输出参数的存储过程 2.4 流程控制语句IF语句WH…...
C# 图表控件库 ScottPlot
推荐使用ScottPlot原因: 1.图形界面简洁,样式丰富 2.代码较少 3.官方提供多种实例源码,并可以直接通过图形界面查看,便于快速开发 Github源码链接:https://github.com/ScottPlot/ScottPlot 官网WindowFrom Demo实例…...
013 怎么查看自己电脑的wifi密码
方法一:查看当前电脑连接的无线密码 步骤1: 打开windows命令行窗口,输入:ncpa.cpl 快速打开“控制面板”中的“网络连接”,如下图: 步骤2: 右键,打开“状态” 步骤3:…...
深入了解 LoRaWAN® MAC 命令
本文深入探讨了用于 LoRaWAN 网络管理的 MAC 命令。它面向终端设备软件开发人员和使用 LoRa 构建设备的团队经理,这些设备实现了LoRaWAN 链路层规范 v1.0.4。本文帮助您了解不同类型的 MAC 命令、每个命令的用途以及如何解释这些命令。 已经使用LoRaMAC-Node™等软件来处理 MA…...
跨境电商与隐擎fox指纹浏览器:保障安全与效率的完美结合
随着全球化的发展,跨境电商已成为各国贸易的重要组成部分。然而,随之而来的风险和挑战也日益增多,其中之一就是关联浏览器和多开浏览器可能带来的安全隐患。为了确保跨境电商的顺利运营和数据安全,隐擎fox指纹浏览器作为一种防关联…...
【网络编程】五种网络IO模式
对于一次IO访问(以read为例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,会经历两个阶段: 1、等待数据准…...
面试总结-2023版
本文受众主要为,互联网技术研发人员。 技术面试一般三面和HRBP面不太会卡人,主要都是停在了一面和二面上。我这次换工作前期主要是一面通过率比较低,后面主要是二面通过低。 总结影响面试通过的几点因素: 是否真的招人…...
bigemap在草原行业的应用案例
一.为什么选择Bigemap 1.使用软件一般都用于套坐标以及空间规划图,方便于项目选址和居民建房报建 2.在卫星图上找到用地范围,然后打点,导出点位范围的2000坐标,用于汇报出图 3.CGCS2000坐标系通过矢量转换转成地方坐标系...
DevOps系列文章之 java调用python脚本
在java类中直接执行python语句 在java类中直接调用本地python脚本 使用Runtime.getRuntime()执行python脚本文件(推荐) 调用python脚本中的函数 简单介绍 官网地址 首页 | (jython.org) Jython项目提供了Java中的Python实现, 为Python提供了…...
PHP异步框架总结
目前主要有: 国产 swoole workerman 国外 framework-x revoltrevolt reactphp amphp async...
vsto excel 可以异步写入值么
在 VSTO (Visual Studio Tools for Office) 中,Excel 可以使用异步方式写入值。异步编程允许您在后台线程中执行耗时的操作,而不会阻塞主线程,从而提高程序的响应性能。 从 .NET 4.5 开始,可以使用异步和 await 关键字来简化异步…...
Android Gradle 骚操作,将两个项目合并到一个项目中
1. 前言 在工作中,由于各种原因,导致需要将两个可单独运行的App项目,合并到一个git仓库里,且单独的App项目里还有其他Module模块。 如果只是将两个项目复制到同一个文件夹下,还是得单独打开各个项目,是很不…...
虹科案例|如何分析设备故障时间和次数,打破生产瓶颈?
虹科设备绩效管理系统 保障生产设备的稳定性和可靠性 生产设备的稳定性和可靠性是保证企业正常生产的重要条件之一,设备故障的频发严重影响企业的正常生产,那么如何分析设备故障时间和次数,查找设备故障原因,协助企业打破生产瓶…...
SVN代码迁移到Git方法
1.在SVN上新增一个项目 一、点击新建项目 二、创建空白项目 三、填入项目信息 四、myProject项目模板创建成功 2.将代码提交到Git 一、新建一个文件夹myProject,将从SVN下载过来的代码复制一份拷贝到该文件夹下,注意:不要把.SVN文件拷…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
