mybatis-plus 的 page 对象需用 @param("page") 显式命名后,xml 中通过 #{page.current} 和 #{page.size} 访问;联表分页需手动写 count 和 list 两个 sql,且字段、类型、条件须严格一致。

MyBatis-Plus 的 Page 对象怎么传进 XML 自定义 SQL
不能直接当参数塞进 <select></select> 标签里——Page 不是普通 POJO,它不会自动拆成 current 和 size 供 XML 引用。XML 里只能认你显式传进去的参数,比如 Map 或带 @Param 的对象。
正确做法是:在 Mapper 接口方法中,把 Page<t></t> 和业务参数一起传入,并用 @Param 显式命名;XML 中通过 #{page.current}、#{page.size} 访问(前提是 page 是 @Param("page") 绑定的)。
- 接口方法必须声明
Page<t></t>为参数,且加@Param("page"),否则 MyBatis 找不到page这个变量名 - XML 中分页参数必须写成
#{page.current}和#{page.size},不是#{current}或#{page} - 别漏掉
LIMIT #{page.size} OFFSET #{page.current}的计算逻辑——MyBatis-Plus 不会帮你算OFFSET,得自己写#{page.current} * #{page.size}或改用ROW_NUMBER()等数据库特性
XML 里写联表查询时,Page 分页为什么总查全表或报错
因为 MyBatis-Plus 的自动分页插件(PaginationInnerInterceptor)默认只对简单 SELECT 生效,遇到 JOIN、子查询、GROUP BY 就大概率失效——它尝试用 SELECT COUNT(*) FROM (your_sql) 包裹原 SQL 做总数统计,但联表后别名、字段歧义、括号嵌套会让这个包裹失败。
常见错误现象:org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'xxx' in class class java.lang.Integer,或分页结果为空但总数是 0。
- 手动写两个 SQL:一个带
count(1)的统计语句(用相同JOIN和WHERE),一个带LIMIT/OFFSET的查询语句 - 在 XML 中用
<select id="selectListWithPage" resulttype="map"></select>写查询,再配一个<select id="selectCountWithPage" resulttype="long"></select> - 确保两个 SQL 的
WHERE条件完全一致,否则总数和列表对不上
Page<t></t> 和自定义返回类型(如 Map 或 VO)怎么配合
XML 返回类型写 resultType="map" 或 resultType="com.example.UserOrderVO" 没问题,但 Page 的泛型 T 必须和实际返回类型一致,否则 records 列表里对象类型错乱,字段映射失败。
例如 XML 返回的是 UserOrderVO 字段,但你声明 Page<user></user>,那 records 里每个元素都会被强转成 User,字段丢失或抛 ClassCastException。
- Mapper 方法签名必须和 XML
resultType严格匹配:Page<userordervo> selectPageWithJoin(@Param("page") Page<userordervo>, @Param("query") QueryDTO)</userordervo></userordervo> - VO 类字段名要和 SQL 查询结果列名一致(或用
<resultmap></resultmap>映射),别依赖驼峰自动转换——联表后列名常带前缀如u.id、o.order_no,XML 里得写成column="u.id" property="userId" - 如果用
Map接收,Page<map object>></map>可以,但后续取值全是map.get("user_name"),容易写错键名
为什么加了 PaginationInnerInterceptor,XML 自定义 SQL 还是没分页
拦截器默认只拦截 Mapper 接口上没加 @Select、没指向 XML 的方法。一旦你写了 @SelectProvider 或方法体里调用 sqlSession.selectList("xml.namespace.id", ...),就绕过了 MP 的分页逻辑。
最典型的坑:在 Service 层手写 sqlSession.selectList("mapper.UserMapper.selectWithJoin", params),这时候 Page 参数再怎么传,拦截器也看不到。
- 必须走 Mapper 接口方法调用,且该方法没有
@Select注解(否则走注解 SQL,不进 XML) - 确认
mybatis-plus.configuration.default-scripting-language-driver没被覆盖,否则 XML 解析可能异常 - Spring Boot 项目检查是否漏配
MybatisPlusConfig,里面MybatisPlusInterceptor要包含PaginationInnerInterceptor实例
联表分页这事,核心就卡在“谁负责分页”——是 MP 插件自动包 SQL,还是你手动控制 count + limit。选了后者,Page 就只是个参数容器,别指望它自动变魔法。字段映射、类型对齐、SQL 一致性,三处漏一点,分页就静默失效。










