引言
在 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 的分頁機制,有助于避免類似問題,提高開發效率。