分页查询
PageResult 实体类
根据前端页面原型分析,可以知道需要响应的数据为 total(总记录数)和 rows(当前页数据列表)
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageResult {
private Long total; //总记录数
private List rows; //当前页数据列表
}原始方式
EmpController
设置请求参数默认值:@RequestParam(defaultValue="默认值")
java
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page ,
@RequestParam(defaultValue = "10") Integer pageSize){
log.info("查询员工信息, page={}, pageSize={}", page, pageSize);
PageResult pageResult = empService.page(page, pageSize);
return Result.success(pageResult);
}
}EmpService
java
public interface EmpService {
/**
* 分页查询
* @param page 页码
* @param pageSize 每页记录数
*/
PageResult page(Integer page, Integer pageSize);
}EmpServiceImpl
java
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public PageResult page(Integer page, Integer pageSize) {
//1. 获取总记录数
Long total = empMapper.count();
//2. 获取结果列表
Integer start = (page - 1) * pageSize;
List<Emp> empList = empMapper.list(start, pageSize);
//3. 封装结果
return new PageResult(total, empList);
}
}EmpMapper
java
@Mapper
public interface EmpMapper {
/**
* 查询总记录数
*/
@Select("select count(*) from emp e left join dept d on e.dept_id = d.id ")
public Long count();
/**
* 查询所有的员工及其对应的部门名称
*/
@Select("select e.*, d.name deptName from emp as e left join dept as d on e.dept_id = d.id limit #{start}, #{pageSize}")
public List<Emp> list(Integer start , Integer pageSize);
}PageHelper 分页插件
问题引入
前面我们已经完了基础的分页查询,大家会发现:分页查询功能编写起来比较繁琐。 而分页查询的功能是非常常见的,我们查询员工信息需要分页查询,将来在做其他项目时,查询用户信息、订单信息、商品信息等等都是需要进行分页查询的
而分页查询的思路、步骤是比较固定的。 在 Mapper 接口中定义两个方法执行两条不同的 SQL 语句:
(1)查询总记录数
(2)指定页码的数据列表
在 Service 当中,调用 Mapper 接口的两个方法,分别获取:总记录数、查询结果列表,然后在将获取的数据结果封装到 PageBean 对象中
思考一个问题
在未来开发其他项目,只要涉及到分页查询功能(例:订单、用户、支付、商品),都必须按照以上操作完成功能开发
结论
原始方式的分页查询,存在着"步骤固定"、"代码频繁"的问题
解决方案
可以使用一些现成的分页插件完成。对于 Mybatis 来讲现在最主流的就是 PageHelper
基本介绍
PageHelper 是第三方提供的 Mybatis 框架中的一款功能强大、方便易用的分页插件,支持任何形式的单标、多表的分页查询
官网:https://pagehelper.github.io/

Mapper 接口层
(1)原始的分页查询功能中,我们需要在 Mapper 接口中定义两条 SQL 语句
(2)PageHelper 实现分页查询之后,只需要编写一条 SQL 语句,而且不需要考虑分页操作,就是一条正常的查询语句
Service 层
(1)需要根据页码、每页展示记录数,手动的计算起始索引
(2)无需手动计算起始索引,直接告诉 PageHelper 需要查询那一页的数据,每页展示多少条记录即可
pom.xml 中引入依赖
xml
<!--分页插件PageHelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>EmpMapper
之前有关分页的操作现都无需考虑,引入 PageHelper 插件后底层会对 SQL 语句进行拼接与替换,实现分页查询
java
@Mapper
public interface EmpMapper {
// -------------------原始分页操作,使用 PageHelper 插件后无需分页相关考虑,插件底层做了封装-------------------
//
// /**
// * 查询总记录数
// */
// @Select("select count(*) from emp e left join dept d on e.dept_id = d.id ")
// public Long count();
//
// /**
// * 查询所有的员工及其对应的部门名称
// */
// @Select("select e.*, d.name deptName from emp as e left join dept as d on e.dept_id = d.id limit #{start}, #{pageSize}")
// public List<Emp> list(Integer start , Integer pageSize);
/**
* 查询所有的员工及其对应的部门名称
* 使用 PageHelper,无需考虑分页相关的操作,在执行时会对 SQL 语句进行拼接与替换
*/
@Select("select e.*, d.name deptName from emp as e left join dept as d on e.dept_id = d.id")
public List<Emp> list();
}EmpServiceImpl
java
@Override
public PageResult page(Integer page, Integer pageSize) {
//1. 设置分页参数
PageHelper.startPage(page,pageSize);
//2. 执行查询
List<Emp> empList = empMapper.list();
Page<Emp> p = (Page<Emp>) empList;
//3. 封装结果
return new PageResult(p.getTotal(), p.getResult());
}相关方法小结
(1)设置分页参数
java
PageHelper.startPage(page,pageSize);(2)PageHelper 中有一个封装对象 Page
可以把返回的集合强转为 Page 对象
(3)调用 Page 对象的相关方法返回数据
获取总记录数:getTotal()
获取当前页数据列表:getResult()
实现机制
我们打开 Idea 的控制台,可以看到在进行分页查询时,输出的 SQL 语句

我们看到执行了两条 SQL 语句,而这两条 SQL 语句,其实是从我们在 Mapper 接口中定义的 SQL 演变而来的。
(1)第一条 SQL 语句,用来查询总记录数。

其实就是将我们编写的 SQL 语句进行的改造增强,将查询返回的字段列表替换成了 count(0) 来统计总记录数
(2)第二条 SQL 语句,用来进行分页查询,查询指定页码对应 的数据列表

其实就是将我们编写的 SQL 语句进行的改造增强,在 SQL 语句之后拼接上了 limit 进行分页查询,而由于测试时查询的是第一页,起始索引是 0,所以简写为 limit?
而 PageHelper 在进行分页查询时,会执行上述两条 SQL 语句,并将查询到的总记录数,与数据列表封装到了 Page<Emp> 对象中,我们再获取查询结果时,只需要调用 Page 对象的方法就可以获取
⚠️ 注意事项
(1)PageHelper 实现分页查询时,SQL 语句的结尾一定一定一定不要加分号(;)
(2)PageHelper 只会对紧跟在其后的第一条 SQL 语句进行分页处理
