MyBatis實(shí)現(xiàn)分頁(yè)全過(guò)程
下面我將詳細(xì)講解MyBatis實(shí)現(xiàn)分頁(yè)的幾種方式,通過(guò)通俗易懂的故事和代碼示例幫助理解:
故事背景
假設(shè)我們經(jīng)營(yíng)一個(gè)"圖書管理系統(tǒng)",數(shù)據(jù)庫(kù)中有10萬(wàn)本圖書。
當(dāng)用戶查看圖書列表時(shí),一次性加載所有數(shù)據(jù)會(huì)導(dǎo)致系統(tǒng)崩潰(就像把整個(gè)圖書館的書都堆在收銀臺(tái)上)。
這時(shí)就需要分頁(yè)功能——每次只展示"一架子書"(如每頁(yè)20本)。
一、MyBatis實(shí)現(xiàn)分頁(yè)的三種方式
1.手動(dòng)SQL分頁(yè)(物理分頁(yè))
SELECT * FROM books LIMIT #{start}, #{pageSize}
原理:
直接在SQL中通過(guò)LIMIT
(MySQL)或ROWNUM
(Oracle)控制數(shù)據(jù)范圍。
代碼示例:
// Mapper接口 List<Book> getBooksByPage(@Param("start") int start, @Param("pageSize") int pageSize); // 調(diào)用方式(獲取第3頁(yè),每頁(yè)20條) int pageNum = 3; int pageSize = 20; List<Book> books = bookMapper.getBooksByPage((pageNum-1)*pageSize, pageSize);
? 優(yōu)點(diǎn):
- 性能最佳(數(shù)據(jù)庫(kù)只返回所需數(shù)據(jù))
- 完全掌控SQL邏輯
? 缺點(diǎn):
- 需手動(dòng)計(jì)算偏移量(如
(pageNum-1)*pageSize
) - 不同數(shù)據(jù)庫(kù)語(yǔ)法不同(MySQL用LIMIT,Oracle用ROWNUM)
2.RowBounds分頁(yè)(邏輯分頁(yè))
RowBounds rowBounds = new RowBounds(40, 20); // 跳過(guò)前40條,取20條 List<Book> books = sqlSession.selectList("getAllBooks", null, rowBounds);
原理:
先查詢所有數(shù)據(jù)到內(nèi)存,再在Java層截取指定范圍(像把整個(gè)圖書館的書運(yùn)到倉(cāng)庫(kù),再挑出20本)。
? 優(yōu)點(diǎn):
- 使用簡(jiǎn)單,無(wú)需改SQL
? 缺點(diǎn):
- 性能災(zāi)難(數(shù)據(jù)量大時(shí)內(nèi)存溢出)
- 實(shí)際工作中禁止使用!
3.分頁(yè)插件(推薦方案)
使用PageHelper插件(最主流方案):
// 只需在查詢前設(shè)置分頁(yè)參數(shù) PageHelper.startPage(3, 20); // 第3頁(yè),每頁(yè)20條 List<Book> books = bookMapper.selectAllBooks(); // 獲取分頁(yè)信息 PageInfo<Book> pageInfo = new PageInfo<>(books); System.out.println("總頁(yè)數(shù):" + pageInfo.getPages());
原理:
通過(guò)MyBatis攔截器自動(dòng)改寫SQL,添加LIMIT
語(yǔ)句(像有個(gè)智能機(jī)器人幫你從書架上拿指定范圍的書)。
配置步驟:
- 添加依賴:
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.2</version> </dependency>
- 配置攔截器(mybatis-config.xml):
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"/> </plugins>
? 優(yōu)點(diǎn):
- 零侵入(不改動(dòng)原SQL)
- 自動(dòng)適配不同數(shù)據(jù)庫(kù)
- 返回豐富分頁(yè)信息(總頁(yè)數(shù)/當(dāng)前頁(yè)等)
二、分頁(yè)原理對(duì)比表
方式 | 性能 | 易用性 | 適用場(chǎng)景 |
---|---|---|---|
手動(dòng)SQL分頁(yè) | ???? | ?? | 簡(jiǎn)單SQL,明確數(shù)據(jù)庫(kù)類型 |
RowBounds | ? | ???? | 禁止生產(chǎn)使用 |
PageHelper | ???? | ????? | 99%的生產(chǎn)場(chǎng)景 |
三、總結(jié)
絕對(duì)避免使用RowBounds
邏輯分頁(yè)(除非數(shù)據(jù)量極小)
簡(jiǎn)單場(chǎng)景可用手動(dòng)SQL分頁(yè)(需處理數(shù)據(jù)庫(kù)差異)
PageHelper是終極解決方案:
- 自動(dòng)生成分頁(yè)SQL
- 統(tǒng)一不同數(shù)據(jù)庫(kù)行為
- 返回完整分頁(yè)元數(shù)據(jù)
百萬(wàn)級(jí)數(shù)據(jù)分頁(yè)優(yōu)化:
-- 使用索引覆蓋優(yōu)化 SELECT * FROM books WHERE id >= (SELECT id FROM books ORDER BY id LIMIT 1000000, 1) LIMIT 20
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java匿名內(nèi)部類導(dǎo)致內(nèi)存泄露的原因與解決方案詳解
這篇文章主要為大家詳細(xì)介紹了Java因?yàn)槟涿麅?nèi)部類導(dǎo)致內(nèi)存泄露的原因以及其解決方案,文中的示例代碼講解詳細(xì),希望對(duì)大家有所幫助2022-11-11Java模擬實(shí)現(xiàn)HTTP服務(wù)器項(xiàng)目實(shí)戰(zhàn)
本文主要介紹了Java模擬實(shí)現(xiàn)HTTP服務(wù)器項(xiàng)目實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Java 動(dòng)態(tài)生成類和實(shí)例, 并注入方法操作示例
這篇文章主要介紹了Java 動(dòng)態(tài)生成類和實(shí)例, 并注入方法操作,結(jié)合實(shí)例形式分析了Java 動(dòng)態(tài)生成類和實(shí)例以及動(dòng)態(tài)注入相關(guān)操作技巧,需要的朋友可以參考下2020-02-02Java代理模式與動(dòng)態(tài)代理之間的關(guān)系以及概念
代理模式是開發(fā)中常見的一種設(shè)計(jì)模式,使用代理模式可以很好的對(duì)程序進(jìn)行橫向擴(kuò)展。動(dòng)態(tài)代理:代理類在程序運(yùn)行時(shí)被創(chuàng)建的代理方式。關(guān)鍵在于動(dòng)態(tài),程序具有了動(dòng)態(tài)特性,可以在運(yùn)行期間根據(jù)不同的目標(biāo)對(duì)象生成動(dòng)態(tài)代理對(duì)象2023-02-02Java內(nèi)部類的實(shí)現(xiàn)原理與可能的內(nèi)存泄漏說(shuō)明
這篇文章主要介紹了Java內(nèi)部類的實(shí)現(xiàn)原理與可能的內(nèi)存泄漏說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Spring IOC:CreateBean環(huán)節(jié)中的流程轉(zhuǎn)換
Spring IOC 體系是一個(gè)很值得深入和研究的結(jié)構(gòu) , 只有自己真正的讀一遍 , 才能有更好的理解.這篇文章主要說(shuō)明一下 CreateBean 整個(gè)環(huán)節(jié)中的大流程轉(zhuǎn)換 , 便于查找問題的原因2021-05-05