分页查询插件PageHelp的使用模板,以及底层实现的简单了解

1.需求

分页查询在业务中很普遍,前端给的参数通常有两个:
当前页数page(从1开始,即第几页);
每页大小pageSize

基于sql实现,需要自己写select * from xx limit offset, nums;
表示查询从index为offset的记录开始,的往后nums条记录,注意offset是从0开始的。

sql所需要的两个参数,与前端传参是不匹配的,存在一个转换公式:
o f f s e t = ( p a g e − 1 ) × p a g e S i z e offset = (page-1)\times pageSize offset=(page1)×pageSize
n u m s = p a g e S i z e nums=pageSize nums=pageSize

当然可以自己做如上转化,但麻烦,有没有更快捷的方式呢?

2.思路

使用MyBatis分页插件PageHelper,接收前端传参后自动转换

3.解决方案

引入插件:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>

使用模板(service层的分页查询函数):

//员工分页查询
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
    //开始分页
    PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());

    //返回类型是Page,泛型为单条记录的实体类
    Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

    //service层给controller层返回的数据封装为PageResult
    long total = page.getTotal();//总记录数
    List<Employee> records = page.getResult();//记录列表
    return new PageResult(total, records);
}

这里我用的是xml,方便写动态sql,注意:sql语句中不要自己再写limit了!! PageHelper会自动拼接limit相关语句

<mapper namespace="com.sky.mapper.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from employee
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
        </where>
        order by create_time desc
    </select>
</mapper>

分析:
1.拿的参数就是前端给的page页码,和pageSize每页数量
2.PageHelper.startPage开始分页
3.调用mapper查询,返回类型是Page<单条记录的实体类>,这玩意其实就是个List
4.返回给controller有两部分内容:总记录数,和查询到的记录。为什么要有总记录数? 因为前端要根据总记录数计算总共有多少页呀。

4.底层实现,两个问题

4.1 PageHelper.startPage怎么对后续查询起作用的

代码里面,似乎没有看到后续过程中调用PageHelper,怎么生效的呢?
查看startPage源码,经过几个重载后:

public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
    Page<E> page = new Page<E>(pageNum, pageSize, count);
    page.setReasonable(reasonable);
    page.setPageSizeZero(pageSizeZero);
    //当已经执行过orderBy的时候
    Page<E> oldPage = getLocalPage();
    if (oldPage != null && oldPage.isOrderByOnly()) {
        page.setOrderBy(oldPage.getOrderBy());
    }
    setLocalPage(page);
    return page;
}

实例化了一个page对象,包含了pageNum和pageSize两个关键的分页参数,Page类继承ArrayList。

倒数第三行:setLocalPage(page);

protected static void setLocalPage(Page page) {
    LOCAL_PAGE.set(page);
}

LOCAL_PAGE又是啥?

protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();

LOCAL_PAGE是个ThreadLocal对象,即将page作为当前线程变量。

以下只是我的简单理解,具体调用我也没搞明白…
page对象成为当前线程变量后,在“需要的时候”取出来,做两件事情:
1.自动计算sql需要的offset和nums。
2.在自定义的sql语句中,拼接limit以及参数

4.2 总记录数怎么获取的

仍然是简单理解,没定位到源码部分
在执行4.1的拼接limit后的sql语句之前,会自动先执行select count(0) from xxx获取总记录数
在这里插入图片描述
注意:如果查询带条件where,count(0)查询总数时也是带条件的。
这个总数,指的是满足你查询条件的总记录数,而非表中所有记录数量

暂且记录到此,以后有机会再去研究底层实现,先记录PageHelper的使用方式。

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设你使用的是 Java Spring Boot 框架,可以使用 MyBatis 分页插件进行分页查询。 首先,在 pom.xml 中添加 MyBatis 分页插件的依赖: ```xml <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> ``` 然后,在需要进行分页查询的方法中,调用 PageHelper.startPage() 方法开启分页功能,并传入当前页码和每页显示的数据条数,如下所示: ```java import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public PageInfo<User> getUsers(int pageNum, int pageSize) { PageHelper.startPage(pageNum, pageSize); List<User> users = userMapper.getUsers(); return new PageInfo<>(users); } } ``` 在上面的代码中,我们调用了 PageHelper.startPage() 方法开启分页功能,并传入了当前页码和每页显示的数据条数。然后,我们调用 UserMapper 接口中的 getUsers() 方法来获取所有用户数据,并将其封装成 PageInfo 对象返回。 最后,我们可以在控制器中调用 getUsers() 方法来获取分页数据,并将其返回给前端页面显示,如下所示: ```java @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/users") public PageInfo<User> getUsers(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize) { return userService.getUsers(pageNum, pageSize); } } ``` 在上面的代码中,我们使用 @GetMapping 注解来处理 GET 请求,并通过 @RequestParam 注解来获取请求参数中的当前页码和每页显示的数据条数。然后,我们调用 UserService 接口中的 getUsers() 方法来获取分页数据,并将其返回给前端页面显示。 至此,我们就完成了后端使用分页插件实现分页查询的代码编写。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值