MyBatis-Plus 分页失效问题解析:@Param 注解的影响与解决方案
引言
在 Spring Boot + MyBatis-Plus 的开发中,分页查询是常见的需求。
然而,有时我们会遇到分页失效的问题,尤其是在方法参数上添加 @Param
注解后。
本文将通过一个实际案例,分析 @Param
注解如何影响 MyBatis-Plus 的分页机制,并提供解决方案。
问题重现
1. 原始代码
在 AlertServiceImpl
中,分页查询方法 page()
调用了 AlertDao
的 list()
方法:
@Override
public PageData<AlertDTO> page(Map<String, Object> params) {IPage<AlertEntity> page = getPage(params, null, false);List<AlertDTO> list = baseDao.list(params);return getPageData(list, page.getTotal(), AlertDTO.class);
}
AlertDao
的 list()
方法如下:
@DataSource(name = DataSourceNames.SECOND)
List<AlertDTO> list(@Param("p") Map<String, Object> params);
此时,分页失效,SQL 查询返回所有数据,而不是分页后的结果。
2. 修复后的代码
移除 @Param("p")
后,分页恢复正常:
@DataSource(name = DataSourceNames.SECOND)
List<AlertDTO> list(Map<String, Object> params);
原因分析
1. MyBatis-Plus 的分页机制
MyBatis-Plus 的分页插件(PaginationInterceptor
)会在执行 SQL 前自动解析分页参数(如 page
、size
),并修改 SQL 添加 LIMIT
子句。
2. @Param 注解的影响
- 不加
@Param
:MyBatis-Plus 能直接读取Map<String, Object>
中的分页参数(如params.get("page")
),并正确分页。 - 加
@Param("p")
:整个Map
被包装成命名参数p
,MyBatis-Plus 无法直接访问p.page
和p.size
,导致分页插件无法识别分页参数,最终 SQL 没有LIMIT
子句,返回全部数据。
解决方案
方案 1:移除 @Param 注解(推荐)
@DataSource(name = DataSourceNames.SECOND)
List<AlertDTO> list(Map<String, Object> params);
优点:
- 保持 MyBatis-Plus 默认分页行为,无需额外修改 SQL。
- 代码简洁,符合 MyBatis-Plus 最佳实践。
方案 2:手动分页(适用于必须使用 @Param 的情况)
如果必须使用 @Param
,可以在 XML 中手动添加 LIMIT
:
<select id="list" resultType="io.installer.modules.sys.dto.AlertDTO">SELECT ...<where>hd.is_deleted=0</where>LIMIT #{p.page}, #{p.size}
</select>
缺点:
- 需要手动计算分页偏移量,容易出错。
- 不适用于所有数据库(如 Oracle 需要使用
ROWNUM
)。
方案 3:改用 IPage 参数(最佳 MyBatis-Plus 实践)
@DataSource(name = DataSourceNames.SECOND)
List<AlertDTO> list(IPage<AlertDTO> page, @Param("query") Map<String, Object> params);
优点:
- MyBatis-Plus 自动处理分页逻辑,无需手动干预。
- 支持更灵活的分页查询。
总结
方案 | 适用场景 | 优点 | 缺点 |
移除 @Param | 一般情况 | 简单高效 | 无法自定义参数名 |
手动分页 | 必须使用 @Param | 可控性强 | 需要手动计算分页 |
IPage 参数 | 复杂分页查询 | 符合 MyBatis-Plus 最佳实践 | 需要调整方法签名 |
最佳实践建议:
- 优先移除
@Param**
,让 MyBatis-Plus 自动处理分页。 - 如需自定义参数名,可改用
IPage
参数 +@Param
组合。
结论
在 MyBatis-Plus 中,@Param
注解有时会干扰分页插件的参数解析机制,导致分页失效。通过移除 @Param
或改用 IPage
参数,可以确保分页功能正常工作。理解 MyBatis-Plus 的分页机制,有助于避免类似问题,提高开发效率。