綜合概述
想必大家都有過這樣的體驗,在使用Mybatis時,最頭痛的就是寫分頁了,需要先寫一個查詢count的select語句,然后再寫一個真正分頁查詢的語句,當查詢條件多了之后,會發現真的不想花雙倍的時間寫 count 和 select,幸好我們有 pagehelper 分頁插件,pagehelper 是一個強大實用的 MyBatis 分頁插件,可以幫助我們快速的實現MyBatis分頁功能,而且pagehelper有個優點是,分頁和Mapper.xml完全解耦,並以插件的形式實現,對Mybatis執行的流程進行了強化,這有效的避免了我們需要直接寫分頁SQL語句來實現分頁功能。那么,接下來我們就來一起體驗下吧。
實現案例
接下來,我們就通過實際案例來講解如何使用pagehelper來實現MyBatis分頁,為了避免重復篇幅,此篇教程的源碼基於《Spring Boot:整合MyBatis框架》一篇的源碼實現,讀者請先參考並根據教程鏈接先行獲取基礎源碼和數據庫內容。

添加相關依賴
首先,我們需要在 pom.xml 文件中添加分頁插件依賴包。
pom.xml
<!-- pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
添加相關配置
然后在 application.yml 配置文件中添加分頁插件有關的配置。
application.yml
# pagehelper
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
編寫分頁代碼
首先,在 DAO 層添加一個分頁查找方法。這個查詢方法跟查詢全部數據的方法除了名稱幾乎一樣。
SysUserMapper.java
package com.louis.springboot.demo.dao;
import java.util.List;
import com.louis.springboot.demo.model.SysUser;
public interface SysUserMapper {
int deleteByPrimaryKey(Long id);
int insert(SysUser record);
int insertSelective(SysUser record);
SysUser selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(SysUser record);
int updateByPrimaryKey(SysUser record);
/**
* 查詢全部用戶
* @return
*/
List<SysUser> selectAll();
/**
* 分頁查詢用戶
* @return
*/
List<SysUser> selectPage();
}
然后在 SysUserMapper.xml 中加入selectPage的實現,當然你也可以直接用@Select注解將查詢語句直接寫在DAO代碼,但我們這里選擇寫在XML映射文件,這是一個普通的查找全部記錄的查詢語句,並不需要寫分頁SQL,分頁插件會攔截查詢請求,並讀取前台傳來的分頁查詢參數重新生成分頁查詢語句。
SysUserMapper.xml
<select id="selectPage" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from sys_user </select>
服務層通過調用DAO層代碼完成分頁查詢,這里統一封裝分頁查詢的請求和結果類,從而避免因為替換ORM框架而導致服務層、控制層的分頁接口也需要變動的情況,替換ORM框架也不會影響服務層以上的分頁接口,起到了解耦的作用。
SysUserService.java
package com.louis.springboot.demo.service;
import java.util.List;
import com.louis.springboot.demo.model.SysUser;
import com.louis.springboot.demo.util.PageRequest;
import com.louis.springboot.demo.util.PageResult;
public interface SysUserService {
/**
* 根據用戶ID查找用戶
* @param userId
* @return
*/
SysUser findByUserId(Long userId);
/**
* 查找所有用戶
* @return
*/
List<SysUser> findAll();
/**
* 分頁查詢接口
* 這里統一封裝了分頁請求和結果,避免直接引入具體框架的分頁對象, 如MyBatis或JPA的分頁對象
* 從而避免因為替換ORM框架而導致服務層、控制層的分頁接口也需要變動的情況,替換ORM框架也不會
* 影響服務層以上的分頁接口,起到了解耦的作用
* @param pageRequest 自定義,統一分頁查詢請求
* @return PageResult 自定義,統一分頁查詢結果
*/
PageResult findPage(PageRequest pageRequest);
}
服務實現類通過調用分頁插件完成最終的分頁查詢,關鍵代碼是 PageHelper.startPage(pageNum, pageSize),將前台分頁查詢參數傳入並攔截MyBtis執行實現分頁效果。
SysUserServiceImpl.java
package com.louis.springboot.demo.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.louis.springboot.demo.dao.SysUserMapper;
import com.louis.springboot.demo.model.SysUser;
import com.louis.springboot.demo.service.SysUserService;
import com.louis.springboot.demo.util.PageRequest;
import com.louis.springboot.demo.util.PageResult;
import com.louis.springboot.demo.util.PageUtils;
@Service
public class SysUserServiceImpl implements SysUserService {
@Autowired
private SysUserMapper sysUserMapper;
@Override
public SysUser findByUserId(Long userId) {
return sysUserMapper.selectByPrimaryKey(userId);
}
@Override
public List<SysUser> findAll() {
return sysUserMapper.selectAll();
}
@Override
public PageResult findPage(PageRequest pageRequest) {
return PageUtils.getPageResult(pageRequest, getPageInfo(pageRequest));
}
/**
* 調用分頁插件完成分頁
* @param pageQuery
* @return
*/
private PageInfo<SysUser> getPageInfo(PageRequest pageRequest) {
int pageNum = pageRequest.getPageNum();
int pageSize = pageRequest.getPageSize();
PageHelper.startPage(pageNum, pageSize);
List<SysUser> sysMenus = sysUserMapper.selectPage();
return new PageInfo<SysUser>(sysMenus);
}
}
在控制器SysUserController中添加分頁查詢方法,並調用服務層的分頁查詢方法。
SysUserController.java
package com.louis.springboot.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.louis.springboot.demo.service.SysUserService;
import com.louis.springboot.demo.util.PageRequest;
@RestController
@RequestMapping("user")
public class SysUserController {
@Autowired
private SysUserService sysUserService;
@GetMapping(value="/findByUserId")
public Object findByUserId(@RequestParam Long userId) {
return sysUserService.findByUserId(userId);
}
@GetMapping(value="/findAll")
public Object findAll() {
return sysUserService.findAll();
}
@PostMapping(value="/findPage")
public Object findPage(@RequestBody PageRequest pageQuery) {
return sysUserService.findPage(pageQuery);
}
}
分頁查詢請求封裝類。
PageRequest.java
package com.louis.springboot.demo.util;
/**
* 分頁請求
*/
public class PageRequest {
/**
* 當前頁碼
*/
private int pageNum;
/**
* 每頁數量
*/
private int pageSize;
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
分頁查詢結果封裝類。
PageResult.java
package com.louis.springboot.demo.util;
import java.util.List;
/**
* 分頁返回結果
*/
public class PageResult {
/**
* 當前頁碼
*/
private int pageNum;
/**
* 每頁數量
*/
private int pageSize;
/**
* 記錄總數
*/
private long totalSize;
/**
* 頁碼總數
*/
private int totalPages;
/**
* 數據模型
*/
private List<?> content;
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(long totalSize) {
this.totalSize = totalSize;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public List<?> getContent() {
return content;
}
public void setContent(List<?> content) {
this.content = content;
}
}
分頁查詢相關工具類。
PageUtils.java
package com.louis.springboot.demo.util;
import com.github.pagehelper.PageInfo;
public class PageUtils {
/**
* 將分頁信息封裝到統一的接口
* @param pageRequest
* @param page
* @return
*/
public static PageResult getPageResult(PageRequest pageRequest, PageInfo<?> pageInfo) {
PageResult pageResult = new PageResult();
pageResult.setPageNum(pageInfo.getPageNum());
pageResult.setPageSize(pageInfo.getPageSize());
pageResult.setTotalSize(pageInfo.getTotal());
pageResult.setTotalPages(pageInfo.getPages());
pageResult.setContent(pageInfo.getList());
return pageResult;
}
}
編譯測試運行
啟動應用,訪問:localhost:8088/swagger-ui.html,找到對應接口,模擬測試,結果如下。
參數:pageNum: 1, pageSize: 5

參數:pageNum: 2, pageSize: 4

胡言亂語
傳統分頁有點老,select和count都得搞。
分頁SQL寫不好,內容耦合還不小。
pagehelper幫你搞,使用起來有點屌。
參考資料
PageHelper:https://pagehelper.github.io/
PageHelper手冊:https://pagehelper.github.io/docs/howtouse/

