從基礎(chǔ)到實戰(zhàn)詳解SpringBoot3實現(xiàn)分頁操作的完整指南
前言
在當(dāng)今的互聯(lián)網(wǎng)軟件開發(fā)領(lǐng)域,處理海量數(shù)據(jù)是一個繞不開的話題。想象一下,你開發(fā)的應(yīng)用程序需要展示數(shù)以萬計甚至更多的用戶信息、商品列表或者文章內(nèi)容,如果一次性將所有數(shù)據(jù)加載到前端,不僅會嚴(yán)重拖慢系統(tǒng)響應(yīng)速度,還可能導(dǎo)致應(yīng)用程序崩潰。這時候,分頁操作就如同救星一般登場,它能將數(shù)據(jù)合理地分段展示,大大提升用戶體驗和系統(tǒng)性能。今天,咱們就深入探討在 Spring Boot3 中如何巧妙實現(xiàn)分頁操作。
為什么要使用分頁
在現(xiàn)代 Web 應(yīng)用開發(fā)的大環(huán)境下,分頁和排序已然成為處理海量數(shù)據(jù)時,提升用戶體驗與系統(tǒng)性能的關(guān)鍵所在。它們宛如一對默契的搭檔,廣泛應(yīng)用于 RESTful API、后臺管理系統(tǒng)等諸多場景。據(jù) 2024 年 Stack Overflow 開發(fā)者調(diào)查顯示,約 60% 的后端開發(fā)者在處理列表數(shù)據(jù)時會使用分頁技術(shù)。就拿常見的電商平臺商品展示頁面來說,當(dāng)用戶搜索 “運動鞋”,可能會出現(xiàn)成千上萬條結(jié)果,如果不分頁,用戶不僅要等待漫長的加載時間,而且面對滿屏密密麻麻的數(shù)據(jù),也會無從下手。分頁操作通過將數(shù)據(jù)按頁劃分,每次僅加載部分?jǐn)?shù)據(jù),極大地減輕了數(shù)據(jù)庫和服務(wù)器的負(fù)載壓力,讓用戶能夠更高效地瀏覽數(shù)據(jù)。
Spring Boot3 實現(xiàn)分頁的方式
基于 Spring Data JPA 的分頁
Spring Data JPA 為 Java 開發(fā)者提供了極為便捷的方式來實現(xiàn)數(shù)據(jù)訪問層。在分頁方面,它主要通過Pageable接口來達(dá)成。Pageable接口可謂是分頁操作的核心樞紐,它包含了頁碼、每頁大小以及排序信息,能夠生成LIMIT、OFFSET和ORDER BY語句,從而精準(zhǔn)地控制查詢結(jié)果。例如:
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.ASC, "id")); Page<User> users = userRepository.findAll(pageable);
這里通過PageRequest.of方法創(chuàng)建了Pageable實例,指定了當(dāng)前頁碼pageNumber、每頁大小pageSize以及排序方式(按照id字段升序排列)。然后,調(diào)用userRepository的findAll方法,并傳入Pageable實例,即可輕松獲取分頁后的用戶數(shù)據(jù)。Page對象會返回分頁結(jié)果,其中包含了內(nèi)容(content)、分頁信息(pageable)以及總數(shù)(totalElements),為開發(fā)者提供了全面的分頁數(shù)據(jù)。
基于 MyBatis - Plus 的分頁
MyBatis - Plus 是在 MyBatis 基礎(chǔ)上進行增強的工具,它簡化了 MyBatis 的開發(fā)流程,在分頁功能上更是表現(xiàn)出色。實現(xiàn)分頁操作,首先需要引入pagehelper - spring - boot - starter依賴。
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper - spring - boot - starter</artifactId>
<version>最新版本</version>
</dependency>
配置完成后,在代碼中使用PageHelper插件進行分頁操作,簡直易如反掌。例如:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> queryUserListPaged(SysUser user, Integer page, Integer pageSize) {
// 開始分頁
PageHelper.startPage(page, pageSize);
Example example = new Example(SysUser.class);
Example.Criteria criteria = example.createCriteria();
if (!StringUtils.isEmptyOrWhitespace(user.getUsername())) {
criteria.andLike("username", "%" + user.getUsername() + "%");
}
if (!StringUtils.isEmptyOrWhitespace(user.getNickname())) {
criteria.andLike("nickname", "%" + user.getNickname() + "%");
}
List<User> userList = userMapper.selectByExample(example);
return userList;
}
}
在上述代碼中,關(guān)鍵的一行代碼PageHelper.startPage(page, pageSize)就標(biāo)識著分頁操作的開始。PageHelper插件會通過其內(nèi)部強大的攔截器,將原本的查詢 SQL 語句巧妙地轉(zhuǎn)化為分頁 SQL 語句,從而實現(xiàn)高效的分頁查詢。不過,需要特別注意的是,PageHelper.startPage(pageNum, pageSize)方法一定要緊貼在列表查詢方法之前調(diào)用,只有這樣,在查詢時才能準(zhǔn)確查出相應(yīng)的數(shù)據(jù)量,并且同時查詢出數(shù)據(jù)總數(shù)。
分頁實現(xiàn)的詳細(xì)步驟與代碼示例
基于 Spring Data JPA 的完整示例
創(chuàng)建實體類
假設(shè)我們有一個User實體類,用于表示用戶信息。
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
// 其他字段及Getter、Setter方法省略
}
創(chuàng)建 Repository 接口
繼承JpaRepository,Spring Data JPA 會自動為我們實現(xiàn)基本的數(shù)據(jù)訪問方法,包括分頁查詢相關(guān)方法。
public interface UserRepository extends JpaRepository<User, Long> {
}
在 Service 層實現(xiàn)分頁查詢
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Page<User> getUsers(int pageNumber, int pageSize) {
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.ASC, "id"));
return userRepository.findAll(pageable);
}
}
在 Controller 層暴露接口
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public Page<User> getUsers(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return userService.getUsers(page, size);
}
}
此時,訪問/users?page=0&size=10,就可以獲取到第一頁,每頁 10 條數(shù)據(jù)的用戶列表。
基于 MyBatis - Plus 的完整示例
創(chuàng)建實體類
同樣是User實體類,與 Spring Data JPA 示例中的實體類類似。
public class User {
private Long id;
private String username;
private String email;
// 其他字段及Getter、Setter方法省略
}
創(chuàng)建 Mapper 接口
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
在 Service 層實現(xiàn)分頁查詢
前文已經(jīng)展示過該部分代碼,通過PageHelper.startPage方法開啟分頁,然后執(zhí)行查詢邏輯。
在 Controller 層暴露接口
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/paged")
public JSONResult queryUserListPaged(@RequestParam(required = false, defaultValue = "1") Integer page) {
int pageSize = 10;
SysUser user = new SysUser();
List<User> userList = userService.queryUserListPaged(user, page, pageSize);
return JSONResult.ok(userList);
}
}
訪問/users/paged?page=1,即可獲取到使用 MyBatis - Plus 分頁后的用戶列表數(shù)據(jù)。
分頁操作中的性能優(yōu)化與注意事項
性能優(yōu)化
合理設(shè)置每頁數(shù)據(jù)量:如果每頁數(shù)據(jù)量設(shè)置過大,會增加單次查詢的數(shù)據(jù)量,影響查詢速度;如果設(shè)置過小,會導(dǎo)致頻繁查詢數(shù)據(jù)庫,同樣降低性能。一般來說,需要根據(jù)實際業(yè)務(wù)場景和數(shù)據(jù)量大小,經(jīng)過測試來確定一個合適的每頁數(shù)據(jù)量,例如常見的 10 條、20 條或 50 條。
使用索引:對經(jīng)常用于排序和分頁的字段添加索引,可以顯著提升查詢速度。比如在基于 Spring Data JPA 的分頁中,如果按照id字段進行排序和分頁,確保id字段上有索引。在 MySQL 中,可以使用CREATE INDEX語句來創(chuàng)建索引。
避免全表掃描:在編寫查詢語句時,要盡量避免使用SELECT *,而是明確指定需要查詢的字段。這樣可以減少數(shù)據(jù)傳輸量,提高查詢效率。同時,合理使用查詢條件,縮小查詢范圍,避免對整個表進行掃描。
注意事項
調(diào)用順序:在使用 MyBatis - Plus 的PageHelper插件時,startPage()方法必須緊貼在查詢方法之前調(diào)用,否則分頁將無法生效。這是因為PageHelper是通過攔截器機制來實現(xiàn)分頁的,只有正確的調(diào)用順序才能確保攔截器準(zhǔn)確地對查詢 SQL 進行改寫。
線程安全:在異步或多線程場景下,使用PageHelper時需要特別注意線程安全問題。由于PageHelper內(nèi)部依賴ThreadLocal來傳遞分頁參數(shù),如果在多線程環(huán)境下使用不當(dāng),可能會導(dǎo)致參數(shù)混亂,影響分頁結(jié)果。此時,可能需要手動傳遞分頁參數(shù),以確保每個線程的分頁操作獨立且正確。
處理空頁和越界:在返回分頁結(jié)果時,需要考慮到空頁(即查詢結(jié)果為空)和越界(請求的頁碼超出了實際的頁碼范圍)的情況。對于空頁,應(yīng)返回一個合適的提示信息,而不是讓前端顯示空白頁面;對于越界情況,通常應(yīng)返回最后一頁的數(shù)據(jù),或者給出明確的錯誤提示,告知用戶請求的頁碼無效。
動態(tài)排序的實現(xiàn)
在實際業(yè)務(wù)中,除了分頁,動態(tài)排序也是非常常見的需求。用戶可能希望根據(jù)不同的字段,如創(chuàng)建時間、價格、評論數(shù)量等對數(shù)據(jù)進行排序。在 Spring Boot3 中,基于 Spring Data JPA 和 MyBatis - Plus 都能輕松實現(xiàn)動態(tài)排序。
基于 Spring Data JPA 的動態(tài)排序
通過Sort對象或Pageable的排序參數(shù)可以支持動態(tài)排序。例如,我們希望按照用戶的email字段進行降序排序,可以這樣實現(xiàn):
Sort sort = Sort.by(Sort.Direction.DESC, "email"); Pageable pageable = PageRequest.of(pageNumber, pageSize, sort); Page<User> users = userRepository.findAll(pageable);
這里通過Sort.by方法創(chuàng)建了一個按照email字段降序排列的Sort對象,然后將其應(yīng)用到Pageable實例中,最終在查詢時實現(xiàn)了動態(tài)排序。
基于 MyBatis - Plus 的動態(tài)排序
在 MyBatis - Plus 中,同樣可以通過在PageHelper.startPage方法之后,對查詢條件進行動態(tài)排序設(shè)置。假設(shè)我們有一個根據(jù)用戶輸入的排序字段和排序方向進行排序的需求,可以這樣實現(xiàn):
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> queryUserListPaged(SysUser user, Integer page, Integer pageSize, String sortField, String sortDirection) {
PageHelper.startPage(page, pageSize);
QueryWrapper<User> wrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(sortField) &&!StringUtils.isEmpty(sortDirection)) {
wrapper.orderBy(true, "asc".equalsIgnoreCase(sortDirection), sortField);
}
if (!StringUtils.isEmptyOrWhitespace(user.getUsername())) {
wrapper.like("username", "%" + user.getUsername() + "%");
}
if (!StringUtils.isEmptyOrWhitespace(user.getNickname())) {
wrapper.like("nickname", "%" + user.getNickname() + "%");
}
List<User> userList = userMapper.selectList(wrapper);
return userList;
}
}
在上述代碼中,通過QueryWrapper的orderBy方法,根據(jù)傳入的sortField和sortDirection參數(shù)實現(xiàn)了動態(tài)排序功能。
總結(jié)
在 Spring Boot3 中實現(xiàn)分頁操作,無論是基于 Spring Data JPA 還是 MyBatis - Plus,都為開發(fā)者提供了強大且便捷的工具。通過合理運用這些技術(shù),能夠有效地處理海量數(shù)據(jù),提升應(yīng)用程序的性能和用戶體驗。在實際開發(fā)過程中,要根據(jù)項目的具體需求、數(shù)據(jù)庫類型以及團隊技術(shù)棧等因素,選擇合適的分頁實現(xiàn)方式,并注重性能優(yōu)化和各種注意事項。希望本文能為各位互聯(lián)網(wǎng)軟件開發(fā)人員在 Spring Boot3 分頁操作的學(xué)習(xí)和實踐中提供全面而有效的幫助,讓大家在開發(fā)之路上游刃有余。
以上就是從基礎(chǔ)到實戰(zhàn)詳解SpringBoot3實現(xiàn)分頁操作的完整指南的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot分頁的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot在一定時間內(nèi)限制接口請求次數(shù)的實現(xiàn)示例
在項目中,接口的暴露在外面,很多人就會惡意多次快速請求,本文主要介紹了SpringBoot在一定時間內(nèi)限制接口請求次數(shù)的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2022-03-03
IDEA使用jformdesigner插件做管理系統(tǒng)MVC架構(gòu)的步驟和實現(xiàn)思路
在?IntelliJ?IDEA?中結(jié)合?JFormDesigner?插件,通過?Swing?框架實現(xiàn)一個管理系統(tǒng)的?MVC?架構(gòu)是一種經(jīng)典的開發(fā)方式,以下是具體的步驟和實現(xiàn)思路,包含從項目創(chuàng)建到?MVC?架構(gòu)的核心代碼實現(xiàn),需要的朋友可以參考下2024-12-12
基于Nacos實現(xiàn)動態(tài)線程池的設(shè)計與實踐分享
在分布式系統(tǒng)架構(gòu)中,線程池是資源調(diào)度的重要工具,傳統(tǒng)固定參數(shù)的線程池在流量平穩(wěn)的場景下表現(xiàn)良好,但面對現(xiàn)代互聯(lián)網(wǎng)業(yè)務(wù)的潮汐流量特征時,往往會出現(xiàn)資源浪費或處理能力不足的問題,所以本文將介紹基于Nacos實現(xiàn)動態(tài)線程池的設(shè)計與實踐,需要的朋友可以參考下2025-05-05
java sql ResultSet 之getRow()用法說明
這篇文章主要介紹了java sql ResultSet 之getRow()用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
java文件復(fù)制代碼片斷(java實現(xiàn)文件拷貝)
本文介紹java實現(xiàn)文件拷貝的代碼片斷,大家可以直接放到程序里運行2014-01-01
SpringBoot項目中通過@Value給參數(shù)賦值失敗的解決方案
springboot項目中通過@Value給屬性附值失敗,給參數(shù)賦值失敗,打印為空值,文中通過代碼示例給大家介紹的非常詳細(xì),對大家解決問題有一定的幫助,需要的朋友可以參考下2024-04-04
SpringBoot實現(xiàn)阿里云快遞物流查詢的示例代碼
本文將基于springboot實現(xiàn)快遞物流查詢,物流信息的獲取通過阿里云第三方實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2021-10-10

