综合概述
想必大家都有过这样的体验,在使用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.3.0</version> </dependency>
添加相关配置
然后在 application.yml 配置文件中添加分页插件有关的配置。
application.yml
# pagehelper pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql
编写分页代码
首先,在 DAO 层添加一个分页查找方法。这个查询方法跟查询全部数据的方法除了名称几乎一样。
adviseMapper.java
package com.example.mapper;
import org.apache.catalina.LifecycleState;
import org.apache.ibatis.annotations.*;
import com.example.feedback.adviseBean;
import java.util.List;
public interface adviseMapper {
//提交意见反馈
@Insert("insert into feedback(advtype,content,email,other) values(#{advtype},#{content},#{email},#{other})")
@Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true)
public int submitAdvise(@Param("advtype") String type,@Param("content") String content,@Param("email") String email,@Param("other") String other);
//分页查询意见反馈
@Select("select * from feedback")
public List<adviseBean> getAdvicesByPage();
//查询单条反馈的意见
@Select("select * from feedback where id=#{id}")
public adviseBean getAdviceById(long id);
//查询所有建议
@Select("select * from feedback")
public List<adviseBean> getAllAdvices();
//删除意见
@Delete("delete from feedback where id=#{id}")
public int deleteAdviceById(long id);
}
然后在 adviseMapper.xml 中加入selectPage的实现,当然你也可以直接用@Select注解将查询语句直接写在DAO代码,但我们这里选择写在DAO层使用注释的方式,这是一个普通的查找全部记录的查询语句,并不需要写分页SQL,分页插件会拦截查询请求,并读取前台传来的分页查询参数重新生成分页查询语句。
//分页查询意见反馈
@Select("select * from feedback")
public List<adviseBean> getAdvicesByPage();
服务层通过调用DAO层代码完成分页查询,这里统一封装分页查询的请求和结果类,从而避免因为替换ORM框架而导致服务层、控制层的分页接口也需要变动的情况,替换ORM框架也不会影响服务层以上的分页接口,起到了解耦的作用。
服务实现类通过调用分页插件完成最终的分页查询,关键代码是 PageHelper.startPage(pageNum, pageSize),将前台分页查询参数传入并拦截MyBtis执行实现分页效果。
adviseService.java
package com.example.feedback;
import com.example.mapper.adviseMapper;
import com.example.page.PageRequest;
import com.example.page.PageResult;
import com.example.page.PageUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* Created by mingtingjie on 2021/1/13.
*/
@Repository
public class adviseService {
@Autowired
private adviseMapper adMmapper;
//提交意见反馈
public int submitUserAdvise(String advtype,String content,String email,String other){
if(StringUtils.isEmpty(content)){
return -1;
}
return adMmapper.submitAdvise(advtype,content,email,other);
}
//分页查询意见反馈
public PageResult getAdvicesByPage(PageRequest pageRequest){
return PageUtils.getPageResult(pageRequest,getPageInfo(pageRequest));
}
/**
* 调用分页插件pageHepler完成分页
* @return
*/
private PageInfo<adviseBean> getPageInfo(PageRequest pageRequest) {
int pageNum = pageRequest.getPageNum();
int pageSize = pageRequest.getPageSize();
PageHelper.startPage(pageNum, pageSize);
List<adviseBean> adv = adMmapper.getAdvicesByPage();
return new PageInfo<adviseBean>(adv);
}
//查询单条反馈的意见
public adviseBean getAdviceById(long id){
return adMmapper.getAdviceById(id);
}
//查询所有建议
public List<adviseBean> getAllAdvices(){
return adMmapper.getAllAdvices();
}
//根据id删除意见
public int deleteAdviceById(long id){
return adMmapper.deleteAdviceById(id);
}
}
在控制器SysUserController中添加分页查询方法,并调用服务层的分页查询方法。
adviseController.java
package com.example.feedback;
import com.example.async.util.Result;
import com.example.async.util.ResultBean;
import com.example.page.PageRequest;
import com.example.page.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Created by mingtingjie on 2021/1/13.
* 意见反馈
*/
@RestController
@RequestMapping("/api/advise")
public class adviseController {
@Autowired
private adviseService mAdvService;
//提交意见反馈
/**
* 传参@RequestParam 和mapper里面Param选其一即可
* @param advtype
* @param content
* @param email
* @param other
* @return
*/
@RequestMapping(value = "/submit")
public ResultBean submitAdvise(String advtype,String content,String email,String other){
int result = mAdvService.submitUserAdvise(advtype,content,email,other);
if(result==1){
return new ResultBean(200,"success");
}else{
return new ResultBean(400,"error");
}
}
//分页查询意见反馈
@RequestMapping(value = "/getAdvicesByPage")
public Result<adviseBean> getAdvicesByPage(int pageNum,int pageSize){
PageRequest pr = new PageRequest();
pr.setPageNum(pageNum);
pr.setPageSize(pageSize);
PageResult advices = mAdvService.getAdvicesByPage(pr);
Result result = new Result();
if(advices==null){
result.setCode(400);
result.setMsg("null");
result.setData("");
}else{
result.setCode(200);
result.setMsg("success");
result.setData(advices);
}
return result;
}
//查询单条反馈的意见
@RequestMapping(value = "/getAdviceById")
public Result<adviseBean> getAdviceById(long id){
adviseBean adv = mAdvService.getAdviceById(id);
Result result = new Result();
if(adv==null){
result.setCode(400);
result.setMsg("null");
result.setData("");
}else{
result.setCode(200);
result.setMsg("success");
result.setData(adv);
}
return result;
}
//查询所有意见反馈
@RequestMapping(value = "/getAllAdvices")
public Result<adviseBean> getAllAdvises(){
List<adviseBean> advices = mAdvService.getAllAdvices();
Result result = new Result();
if(advices==null){
result.setCode(400);
result.setMsg("null");
result.setData("");
}else{
result.setCode(200);
result.setMsg("success");
result.setData(advices);
}
return result;
}
//根据id删除意见
@RequestMapping(value = "/deleteById")
public ResultBean deleteAdviceById(long id){
int result = mAdvService.deleteAdviceById(id);
if(result==1){
return new ResultBean(200,"success");
}else{
return new ResultBean(400,"error");
}
}
}
分页查询请求封装类。
PageRequest.java
package com.example.page;
/**
* Created by mingtingjie on 2021/1/14.
*/
/**
* 分页请求
*/
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.example.page;
/**
* Created by mingtingjie on 2021/1/14.
*/
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.example.page;
import com.github.pagehelper.PageInfo;
/**
* Created by mingtingjie on 2021/1/14.
*/
public class PageUtils {
/**
* 将分页信息封装到统一的接口
* @param pageRequest
* @param pageInfo
* @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:8089/api/advise/getAdvicesByPage?pageNum=1&pageSize=3,找到对应接口,模拟测试,结果如下。
参数:pageNum: 1, pageSize: 3
参数:pageNum: 2, pageSize: 3
胡言乱语
传统分页有点老,select和count都得搞。
分页SQL写不好,内容耦合还不小。
pagehelper帮你搞,使用起来有点屌。
参考资料
PageHelper:https://pagehelper.github.io/
PageHelper手册:https://pagehelper.github.io/docs/howtouse/