Mybatis/Plus 分頁查詢
分頁查詢的原理是通過將大數(shù)據(jù)量集分割成較小的部分來返回結(jié)果,以減少一次性加載和顯示的數(shù)量。
接受分頁參數(shù):在分頁查詢中,通常會接收兩個關(guān)鍵的參數(shù)——當前頁碼(current)和每頁顯示的數(shù)據(jù)量(size)。這些參數(shù)決定了用戶希望查看哪一部分數(shù)據(jù)。
計算偏移量:根據(jù)當前頁碼和每頁顯示數(shù)據(jù)量,計算出從數(shù)據(jù)庫中哪一行數(shù)據(jù)開始獲取。偏移量公式:
start = (current - 1)* size; start 的值就是數(shù)據(jù)集中的起始位置。
執(zhí)行分頁查詢:在SQL查詢中使用 Limit 字句來限制查詢返回的記錄數(shù)。Limit 接受兩個參數(shù)——偏移量 start 和 每頁顯示的記錄數(shù) size,指示數(shù)據(jù)庫從偏移量處開始,返回指定數(shù)量的記錄。如:
select * from table_name limit start, size; -- 這條語句將從 start 位置開始獲取,獲取 size 條記錄。
還有 像 PageHelper 或 RowBounds 這樣的分頁工具,分頁查詢原理雖然與 Limit 查詢類似,但過程更加簡化和自動化。通過簡化分頁原理,自動處理分頁參數(shù)并返回分頁后的數(shù)據(jù)。
構(gòu)建查詢條件:分頁查詢中,通常還會結(jié)合其他條件(如篩選條件),來進一步縮小查詢范圍。條件可以通過 where 子句進行過濾,以滿足查詢要求。
返回結(jié)果:數(shù)據(jù)庫執(zhí)行查詢后,將結(jié)果集返回給應(yīng)用程序。程序?qū)⒔Y(jié)果進行展示,用戶使用時可以通過調(diào)整頁碼和每頁記錄數(shù),查看不同的部分。
通過分頁查詢,系統(tǒng)可以有效減少內(nèi)存占用和網(wǎng)絡(luò)傳輸?shù)膲毫Γ嵘憫?yīng)速度,特別是在數(shù)據(jù)量非常大的情況下。
1. 在SQL內(nèi)分頁
SQL 使用 Limit。可以直接單表使用,也可以多表實現(xiàn)。
只返回數(shù)據(jù),不返回查詢總數(shù)。
分頁查詢類:
/** * 分頁 */ @Data public class PageShowDto { /** 初始頁 */ private Integer current; /** 數(shù)量 */ private Integer size; /** 開始 */ private Integer start; }
Service實現(xiàn)類:
/** * 查詢 * * @param pageDto 分頁 * @param steamDto 條件 * @return 信息 */ @Override public List<ExerciseSchemeSteamDto> findExerciseType(ExerciseSchemeSteamDto steamDto, PageShowDto pageDto) { pageDto.setStart((pageDto.getCurrent() - 1) * pageDto.getSize()); return exerciseSchemeAndSteamMapper.findExerciseSchemeSteamType(steamDto, pageDto); }
current--起始頁;
size--每頁條數(shù);
pageDto.getCurrent() - 1) * pageDto.getSize()-- 如:(current 3 - 1) * size 10 為 20;此時 start 為 20;
Mappe接口:
/** 查詢 */ List<ExerciseSchemeSteamDto> findExerciseSchemeSteamType(@Param("steamDto") ExerciseSchemeSteamDto steamDto, @Param("pageDto") PageShowDto pageDto);
XML編寫SQL:
<!-- 查詢兩個表 --> <select id="findExerciseSchemeSteamType" resultType="com.control.interactive.entity.dto.ExerciseSchemeSteamDto"> select es.id, es.stage_name as stageName, es.condition_scenario as conditionScenario, es.red_team_action as redTeamAction, ess.team_id as teamId, ess.team_name as teamName, ess.action_command as actionCommand, ess.scheme_id as schemeId from t_exercise_scheme es left join t_exercise_scheme_team ess on es.id = ess.scheme_id <where> <if test="steamDto.stageName != null and steamDto.stageName != ''"> es.stage_name like concat('%', #{steamDto.stageName}, '%') </if> </where> order by es.id <if test="pageDto != null"> limit #{pageDto.size} offset #{pageDto.start} </if> </select>
current--起始頁;
size--每頁條數(shù);
pageDto.getCurrent() - 1) * pageDto.getSize()-- 如:(current 3 - 1) * size 10 為 20;此時 start 為 20;
此時分頁查詢是從 第21條 數(shù)據(jù)開始截取,每頁 10條 數(shù)據(jù)。
查詢直接傳遞參數(shù) current 與 size。想進一步使用條件過濾,直接傳遞相應(yīng)的字段,如 name-模糊查詢等等...
優(yōu)化返回結(jié)果,可以使用 `com.baomidou.mybatisplus.extension.plugins.pagination.Page` 的 Page<> 返回。
2. 使用 PageHelper 插件
PageHelper 是 Mybatis 中常用的分頁插件。再查詢SQL前,自動處理分頁邏輯并為查詢語句添加適當?shù)?Limit 字句。
注入依賴:
<!-- PageHelper 分頁插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.1.6</version> </dependency>
PS:注入依賴使用 注意 與 JSqlParser 的版本沖突,根據(jù)情況進行升降 pagehelper 版本。
自定義分頁查詢類,用于前端傳值:
/** * 分頁 */ @Data public class PageShowDto { /** 初始頁 */ private Integer current; /** 數(shù)量 */ private Integer size; }
ServiceImpl:
初始化分頁:在調(diào)用查詢方法前,通過 PageHelper.startPage(current, size) 設(shè)置當前頁碼和每頁顯示的記錄數(shù)。
~~ PageHelper.startPage(1, 10);
/** * 查詢 * * @param pageDto 分頁 * @param steamDto 條件 * @return 信息 */ @Override public R<PageInfo<ExerciseSchemeSteamDto>> findExercise(PageShowDto pageDto, ExerciseSchemeSteamDto steamDto) { // 分頁參數(shù)設(shè)置 PageHelper.startPage(pageDto.getPageNum(), pageDto.getPageSize()); List<ExerciseSchemeSteamDto> exerciseSchemeSteam = exerciseSchemeAndSteamMapper.findExerciseSchemeSteam(steamDto); PageInfo<ExerciseSchemeSteamDto> steamPageInfo = new PageInfo<>(exerciseSchemeSteam); return R.ok(steamPageInfo); }
PageHelper 攔截SQL語句,再執(zhí)行SQL前自動添加 Limit 和 Offset 子句,便于在數(shù)據(jù)庫表中查詢所需數(shù)據(jù)。
XML SQL 編寫:
/** 查詢 */ List<ExerciseSchemeSteamDto> findExerciseSchemeSteam(@Param("steamDto") ExerciseSchemeSteamDto steamDto);
<!-- 查詢--> <select id="findExerciseSchemeSteam" resultType="com.hrzn.control.interactive.blue.entity.dto.ExerciseSchemeSteamDto"> select es.id as id, es.stage_name as stageName, es.condition_scenario as conditionScenario, es.red_team_action as redTeamAction, ess.team_id as teamId, ess.team_name as teamName, ess.action_command as actionCommand, ess.scheme_id as schemeId from t_exercise_scheme es left join t_exercise_scheme_team ess on es.id = ess.scheme_id <where> <if test="steamDto.stageName != null and steamDto.stageName != ''"> es.stage_name like concat('%', #{steamDto.stageName}, '%') </if> </where> order by es.id; </select>
后臺會通過 PageHelper 將SQL 改為 select (字段) from (表名) limit 0, 10;
返回結(jié)果:查詢完成后,優(yōu)化查詢返回結(jié)果可以使用 PageInfo<>,PageHelper 會將結(jié)果封裝到一個 PageInfo對象,其中包含查詢結(jié)果、總數(shù)據(jù)量、總頁數(shù)等分頁信息。
優(yōu)點:
簡化分頁代碼:只需要調(diào)用 startPage() 方法,分頁邏輯自動處理。
集成度高:與 Mybatis 無縫集成,直接應(yīng)用于現(xiàn)有的 Mybatis 查詢。
簡單使用:http://www.rzrgm.cn/warmNest-llb/p/18120512
3. 使用 RowBounds 分頁
RowBounds 是 Mybatis 自帶的一種分頁處理方式,通過邏輯分頁(在內(nèi)存中分頁)來控制查詢結(jié)果的范圍。
RowBounds:

構(gòu)建查詢:
/** * 查詢 * * @param schemeSteamPage 條件 * @param pageDto 分頁 * @return true */ @Override public List<ExerciseSchemeSteamDto> findExerciseRowBounds(ExerciseSchemeSteamDto schemeSteamPage, PageShowDto pageDto) { RowBounds rowBounds = new RowBounds((pageDto.getCurrent() - 1) * pageDto.getSize(), pageDto.getSize()); return exerciseSchemeAndSteamMapper.findExerciseSchemeSteamRow(schemeSteamPage, rowBounds); }
構(gòu)建 RowBounds 對象:通過 創(chuàng)建一個 RowBounds 對象,傳入偏移量 offsert 和 每頁記錄數(shù) limit;
new RowBounds((pageDto.getCurrent() - 1) * pageDto.getSize(), pageDto.getSize()) 等價于 new RowBounds(offset, size);
offset 從哪行數(shù)據(jù)開始,size 多少條數(shù)據(jù)。
XML 編寫 SQL:
/** 查詢 */ List<ExerciseSchemeSteamDto> findExerciseSchemeSteamRow(@Param("steamDto") ExerciseSchemeSteamDto steamDto, RowBounds rowBounds);
<!-- 演練查詢--> <select id="findExerciseSchemeSteam" resultType="com.hrzn.control.interactive.blue.entity.dto.ExerciseSchemeSteamDto"> select es.id as id, es.stage_name as stageName, es.condition_scenario as conditionScenario, es.red_team_action as redTeamAction, ess.team_id as teamId, ess.team_name as teamName, ess.action_command as actionCommand, ess.scheme_id as schemeId from t_exercise_scheme es left join t_exercise_scheme_team ess on es.id = ess.scheme_id <where> <if test="steamDto.stageName != null and steamDto.stageName != ''"> es.stage_name like concat('%', #{steamDto.stageName}, '%') </if> </where> order by es.id; </select>
查詢與分頁:Mybatis 執(zhí)行查詢時,將結(jié)果集取回后,根據(jù) RowBounds 進行內(nèi)存級別的分頁處理。這種方式下分頁邏輯是在應(yīng)用程序內(nèi)存中執(zhí)行的,而不是在SQL查詢中添加 Limit 子句。
優(yōu)點:
無需改動原始SQL:可以直接作用于已有的 Mybatis 查詢。
缺點:
適合小數(shù)據(jù)集:由于是內(nèi)存中處理分頁邏輯,對于大數(shù)據(jù)集來說性能較差。通常不推薦在大數(shù)據(jù)集上使用 RowBounds 進行分頁。
4. 總結(jié)
直接在SQL內(nèi)分頁,簡單粗暴。
PageHelper 自動化處理分頁查詢,攔截并改寫 SQL,性能高,適合大數(shù)據(jù)集,推薦在 Mybatis 中使用。
RowBounds 則是基于內(nèi)存的分頁方式,簡單直接,但對于大數(shù)據(jù)集性能不佳,通常只適合處理小數(shù)據(jù)集的分頁。

浙公網(wǎng)安備 33010602011771號