当前位置: 首页 > news >正文

Mybatis-Plus的InnerInterceptor插件之beforeQuery方法

beforeQuery - 查询操作前置拦截

  1. 方法签名
void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,ResultHandler resultHandler, BoundSql boundSql)
  1. 用途
  • 在执行查询SQL之前拦截
  • 可以修改查询参数、SQL语句或执行环境
  1. 典型应用场景
  • 动态表名替换
  • 多租户数据过滤
  • SQL性能监控开始
  • 查询条件自动增强

beforeQuery 方法参数详解

beforeQuery 是 MyBatis-Plus 中非常重要的查询拦截方法,参数解析。

  1. Executor executor
  • 作用

MyBatis 执行器,用于执行SQL操作

  • 典型使用场景

获取当前事务状态

执行额外的查询操作

访问缓存

  • 示例
Transaction transaction = executor.getTransaction();
boolean isCommited = transaction.isCommited();
  1. MappedStatement ms
  • 作用

包含了一条SQL语句的所有配置信息

  • 重要属性

id:Mapper方法的全限定名 (如 "com.example.UserMapper.selectById")

sqlCommandType:SQL类型 (SELECT/INSERT/UPDATE/DELETE)

configuration:MyBatis配置对象

  • 示例
String mapperMethod = ms.getId(); // 获取当前执行的Mapper方法
SqlCommandType sqlType = ms.getSqlCommandType(); // 判断SQL类型
  1. Object parameter
  • 作用

Mapper方法传入的参数

  • 处理技巧

可能是单个参数、Map或@Param注解标注的多参数,需要根据实际业务判断参数类型

  • 示例
if (parameter instanceof Map) {Map<?,?> paramMap = (Map<?,?>) parameter;Object idValue = paramMap.get("id");
} else if (parameter instanceof Long) {Long id = (Long) parameter;
}
  1. RowBounds rowBounds
  • 作用

内存分页参数(不推荐使用)

  • 注意

MyBatis-Plus推荐使用IPage进行物理分页

这个参数通常用于兼容旧代码

  • 示例
int offset = rowBounds.getOffset(); // 获取偏移量
int limit = rowBounds.getLimit();   // 获取每页数量
  1. ResultHandler resultHandler
  • 作用

自定义结果集处理器

  • 典型使用

很少在拦截器中直接使用

可用于自定义结果集处理逻辑

  1. BoundSql boundSql
  • 作用

包含最终要执行的SQL和参数映射信息

  • 核心功能

获取和修改SQL语句

访问参数映射

获取参数值

  • 示例
String sql = boundSql.getSql(); // 获取SQL
List<ParameterMapping> mappings = boundSql.getParameterMappings(); // 获取参数映射
Object parameterObject = boundSql.getParameterObject(); // 获取参数对象

测试使用

# 实现额外的业务数据权限,将task.task_id IN ()自动拼写在sql中
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.zq.common.core.domain.TaskIdQuery;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
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 java.sql.SQLException;
import java.util.Map;
import java.util.Set;public class StationPermissionInterceptor implements InnerInterceptor {@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {if (ms.getId().equals("com.zq.mes.craft.mapper.ExecTaskMapper.testPage")) {if (parameter instanceof Map) {Map<?, ?> paramMap = (Map<?, ?>) parameter;Object idValue = paramMap.get("query");TaskIdQuery query = (TaskIdQuery) idValue;Set<Long> taskIds = query.getTaskIds();if (CollectionUtil.isEmpty(taskIds)) {return;}String taskIdsSQL = convertSetToSqlString(taskIds);String originalSql = boundSql.getSql();String whereClause = " WHERE task.task_id IN ( " + taskIdsSQL + " )";String newSql;if (originalSql.contains("WHERE")) {newSql = originalSql.replace("WHERE", whereClause + " AND ");} else if (originalSql.contains("where")) {newSql = originalSql.replace("where", whereClause + " and ");} else {newSql = originalSql + whereClause;}// 使用反射修改SQLReflectUtil.setFieldValue(boundSql, "sql", newSql);}}}public String convertSetToSqlString(Set<Long> ids) {ExpressionList expressionList = new ExpressionList();ids.forEach(id -> expressionList.addExpressions(new LongValue(id)));return expressionList.toString();}
}
# MybatisPlus的配置文件,需将StationPermissionInterceptor加入import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.zq.framework.interceptor.StationPermissionInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;/*** MybatisPlus配置** @author zq*/
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
@RequiredArgsConstructor
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 分页插件interceptor.addInnerInterceptor(paginationInnerInterceptor());// 乐观锁插件interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());// 阻断插件interceptor.addInnerInterceptor(blockAttackInnerInterceptor());// 测试自定义interceptor.addInnerInterceptor(new StationPermissionInterceptor());return interceptor;}/*** 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html*/public PaginationInnerInterceptor paginationInnerInterceptor() {PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();// 设置数据库类型为mysqlpaginationInnerInterceptor.setDbType(DbType.MYSQL);// 设置最大单页限制数量,默认 500 条,-1 不受限制paginationInnerInterceptor.setMaxLimit(-1L);return paginationInnerInterceptor;}/*** 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html*/public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {return new OptimisticLockerInnerInterceptor();}/*** 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html*/public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {return new BlockAttackInnerInterceptor();}
}

image

http://www.aitangshan.cn/news/501.html

相关文章:

  • 第二十一天
  • 有限状态自动机理论
  • Mybatis-Plus的InnerInterceptor插件之beforeQuery()
  • xz pixz 的多线程解压缩方法 - tsunchi
  • 苹果容器Apple container是做什么用的?
  • kubernetes-1.32高可用集群部署(kubeadm)
  • 安装pandas和openpyxl
  • pandas用法
  • 第三章 训练初步深入(3)
  • 安装pandas
  • 奥林匹克小丛书小蓝本习题另解或加强(数论卷)(一)
  • 关于磁盘io性能的命令
  • 房屋防水是建筑工程中非常重要的一部分,通常需要根据不同的环境、建筑结构和使用需求来采取相应的防水措施。国家标准对防水工程的要求有详细规定,以下是常见的防水相关国家标准和要求:
  • Hulo 编程语言开发 —— 从源代码到 AST 的魔法转换
  • python中enumerate的作用
  • ly-容斥杂题选讲
  • 前向传播 反向传播
  • Attention 显存计算 推理训练复杂度
  • NLP随记
  • RL 随记
  • top命令详解
  • 2025杭电暑期(8) 最努力的活着 推式子
  • 从输入网址到看到页面:一段看不见的旅程
  • 牛客周赛109补题
  • stress命令详解
  • Nvidia Proprietary GPU Drivers
  • dd命令生成文件详解
  • 关于PVC排水管系统中存水弯设计的常见类型分类表格:
  • 一个好点子,但是我克制住了
  • 软考系统分析师每日学习卡 | [日期:2025-08-11] | [今日主题:数据库设计过程-概念结构设计阶段]