必须指定dbtype.oracle,否则分页sql会误用limit语法而非rownum导致报错;多数据源需隔离配置,不能全局共用;page构造须显式传参pagenum和pagesize,避免默认值失效;禁用pagehelper防止拦截器冲突;开启debug日志验证sql是否含rownum结构。

PaginationInnerInterceptor 必须设为 DbType.ORACLE,否则生成的 SQL 会用错语法(比如拼 LIMIT 而非 ROWNUM),直接报错或返回空结果。
MybatisPlusInterceptor 配置必须用 DbType.ORACLE
新版 MyBatis-Plus(3.4.0+)弃用了 PaginationInterceptor,改用 MybatisPlusInterceptor + PaginationInnerInterceptor。Oracle 分页依赖 ROWNUM 语义,拦截器类型不匹配就会失效。
- 正确写法:
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.ORACLE)); - 错误写法:
new PaginationInnerInterceptor(DbType.MYSQL)或new PaginationInnerInterceptor(DbType.H2) - 若项目同时连多个库(如 Oracle + MySQL),需按数据源隔离配置,不能全局共用一个拦截器
Page 构造必须传参,不能只 new Page()
Page<user> page = new Page();</user> 是常见坑:它默认 current=1、size=10,但部分版本(尤其搭配 YashanDB 时)可能忽略默认值,导致查出全表数据或空集合。
- 显式传参最稳:
Page<user> page = new Page(pageNum, pageSize);</user> - pageNum 从 1 开始,不是 0;传 0 或负数会触发异常或静默归零
- 如果前端传了非法页码(如 pageNum=0),建议在 Controller 层校验,避免穿透到拦截器
YashanDB 可以走 Oracle 模式,但别混用 PageHelper
YashanDB 兼容 Oracle 的 ROWNUM 语法,所以用 DbType.ORACLE 完全可行。但它不兼容 PageHelper 的方言配置(比如 pagehelper.helperDialect=oracle),那是另一套插件体系。
- 只启用 MyBatis-Plus 自带分页,禁用 PageHelper 相关 starter 和配置
- 如果已引入
pagehelper-spring-boot-starter,必须排除,否则两个拦截器打架,SQL 被重写两次 - 验证是否生效:开启 MyBatis 日志(
logging.level.com.yourpackage.mapper=DEBUG),看实际执行 SQL 是否含WHERE ROWNUM ?结构
Oracle 分页性能敏感,注意 total 查询开销
MyBatis-Plus 默认会额外执行一条 SELECT COUNT(*) 获取总条数,Oracle 上全表扫描成本高,尤其大表没走索引时。
- 业务明确不需要总页数(如“下一页”模式),可关掉:
page.setSearchCount(false) - 确保 COUNT 查询能命中索引——避免
COUNT(*)扫描大表,优先建覆盖索引 - YashanDB 对
ROWNUM优化较好,但嵌套子查询深度过大仍可能慢,避免在分页外层再套复杂聚合
ROWNUM 的解析边界比 Oracle 更严格——比如子查询里不能直接 ORDER BY 后接 ROWNUM,MyBatis-Plus 生成的 SQL 已处理这点,但自定义 SQL 时得手动加一层括号包装。











