mybatis分页拦截通过实现interceptor接口,在statementhandler.prepare()处动态重写sql,注入数据库原生分页语法(如mysql的limit/offset),需解析sql、提取分页参数、替换boundsql,并注意线程安全与方言适配。

理解 MyBatis 分页拦截的核心机制
MyBatis 本身不提供物理分页能力,但通过 Executor 层的插件(Interceptor)可以拦截 SQL 执行前的 StatementHandler 或 Executor,动态重写 SQL 添加 LIMIT/OFFSET(MySQL)、ROWNUM(Oracle)或 OFFSET FETCH(SQL Server/PostgreSQL)等数据库原生分页语法,实现真正的物理分页。
编写分页插件的关键步骤
需实现 org.apache.ibatis.plugin.Interceptor 接口,并在 intercept() 中完成 SQL 解析、分页参数提取和 SQL 改写:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
声明拦截目标:通常拦截
StatementHandler.prepare()或Executor.query(),前者更贴近 SQL 构建,推荐使用 -
识别分页请求:从
MappedStatement获取BoundSql,检查参数中是否含Page对象(如 PageHelper 的Page<t></t>或自定义分页参数) - 解析原始 SQL:用正则或 SQL 解析器(如 JSqlParser)提取 SELECT 主体,剥离 ORDER BY、FOR UPDATE 等子句,避免误改
-
注入分页方言:根据
DatabaseId或驱动类型,拼接对应数据库的分页语法。例如 MySQL:SELECT ... FROM ... LIMIT #{offset}, #{limit} -
替换 BoundSql:用新 SQL、新参数映射(
ParameterMapping)构建新BoundSql,通过反射或MetaObject替换原对象
注册插件与配置注意事项
在 MyBatis 配置文件(mybatis-config.xml)或 Spring Boot 的 @Configuration 类中注册插件:
- 通过
<plugins><plugin interceptor="com.example.PageInterceptor">...</plugin></plugins>声明 - 若使用 Spring Boot,可在
SqlSessionFactoryBean的setPlugins()中添加实例 - 务必设置
@Intercepts注解,明确指定type=StatementHandler.class、method="prepare"、args=Connection.class - 注意线程安全:分页参数(如当前页、每页条数)应从 ThreadLocal 或方法参数中获取,不可用成员变量存储
推荐实践:优先使用成熟分页插件
手动实现易出错(如嵌套子查询、UNION、WITH CTE 场景下 SQL 改写失败),建议直接集成经过验证的方案:
-
PageHelper:最主流的 MyBatis 分页插件,支持多数据库方言,自动识别
PageHelper.startPage()调用,无需修改 XML -
MyBatis-Plus 内置分页:若项目已用 MP,直接调用
page()方法,底层通过InnerInterceptor实现 - 自研插件仅在有特殊需求(如审计字段自动注入 + 分页合并)时考虑,且必须覆盖主流 SQL 结构做充分测试
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










