一个简洁的博客网站:http://lss-coding.top,欢迎大家来访
学习娱乐导航页:http://miss123.top/


一、认识 PageHelper

**官网:**https://pagehelper.github.io/

PageHelper 是 Mybatis 的一个插件,其作用是更加方便的进行分页查询。

在一个程序中难免会使用到查询操作,在查询操作中如果数据量太大则需要进行分页查询,分页操作的实现方法有很多,比如:在 mybatis 中 xml 文件中通过 limit 关键字进行分页查询,该插件就是为了简化在 xml 中进行分页操作的工具;好比在 Mybatis-Plus 中也对分页操作进行了封装,通过调用 selectPage() 方法就可以实现分页操作。

1. 在 sql 中使用 limit 进行分页查询

用法:LIMIT [offset,] rows

SELECT * FROM tb_user LIMIT 10, 10
  • offset 是相对于首行的偏移量(首行是 0),rows 是返回条数
  • mapper 中可以传变量,即在实际使用的时候 offset 与 rows 可以用变量替代
2. 使用第三方库进行分页查询

Mybatis 的 PageHelper 插件

好处在实际项目开发中更加的方便

在项目中我们执行一个分页查询时,很多时候还需要知道该查询的其他信息,比如:总数、每页数量、当前页数、是否有上一页或者是否有下一页等等,这些信息如果每次都自己写的话就会太繁琐冗余了,而 PageHelper 插件能够帮助我们更加方便地获取这些信息,大大方便了我们的开发效率。在 Mybatis-Plus 中也对分页查询进行封装,更加的灵活方便,可以参考:http://lss-coding.top/2021/08/05/mybatis-plus/

二、SpringBoot项目中使用

1. 构建一个 SpringBoot 项目

加入一下依赖

<!-- 日志打印,在控制台可以查看 sql 执行的语句 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.1</version>
</dependency>
<!-- pageHelper 插件 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>
<!-- Mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!-- mysql 驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<!-- lombok 插件,生成 getter/setter 方法 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
    <scope>provided</scope>
</dependency>
2. 配置拦截器插件

两种方式可以配置

2.1 通过 yml 配置文件进行配置
# PageHelper 分页插件配置
pagehelper:
  helper-dialect: mysql
  reasonable: true
  support-methods-arguments: true
  params: count=countsql
  • helper-dialect:指定数据库,不指定的话会默认自动检测数据库类型
  • reasonable:是否启动分页合理化。如果启用,当 pagenum < 1 时,会自动查询第一页的数据,当 pagenum > pges 时,自动查询最后一页数据;不启用的,以上两种情况都会返回空数据,如果启用则 pageHelper可以自动拦截请求参数中的 pageNum,pageSize参数,否则需要使用 PageHelper.startPage(pageNum,pageSize) 方法调用。
  • support-methods-arguments:默认为 false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。
  • params:用于从对象中根据属性名取值,可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值,默认值为 pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero

pagehelper分页插件配置信息

#标识是哪一种数据库
pagehelper.helperDialect=mysql
#启用合理化,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页
pagehelper.reasonable=true
#为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
pagehelper.params=count=countSql
#支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页
pagehelper.supportMethodsArguments=true
#如果 pageSize=0 就会查询出全部的结果(相当于没有执行分页查询)
pagehelper.page-size-zero=true

2.2 配置类
@Configuration
public class PageHelperConfiguration {
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}
3. 业务逻辑实现

分页查询 tb_user 表中的数据进行展示

  1. 创建一个 Mapper 接口
@Mapper
public interface UserMapper {

    List<User> getUserList();

}
  1. 在 resources 文件夹下创建与之对应的 xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lss.mapper.UserMapper">

    <select id="getUserList" resultType="User">
        SELECT * FROM tb_user
    </select>

</mapper>

这里需要注意:要在 application.yml 配置文件中进行配置

mybatis:
  # config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true	# 也可以在 yml 配置文件中设置属性
    # 开启日志功能
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  type-aliases-package: com.lss.domain
  1. 创建一个实现层接口
public interface UserService{
    List<User> getUserList();
}
  1. 创建实现层接口的实现类
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> getUserList() {
        // 设置第几条记录开始,多少页记录为一页
        PageHelper.startPage(1,5);
        // 获取 User,sql 语句为 select * from tb_user
        // 因为已经注册了 PageHelper插件,所以 PageHelper会在原 sql 语句上增加 limit,从而实现分页
        List<User> userList = userMapper.getUserList(); // 获得的分好页的结果集
        return userList;
    }
}

  1. 如果想要获取分页的详细信息,修改上面实现类代码
// 获取页面信息的对象,里面封装了很多的页面的信息:总条数、总页数、当前页数量、是否有上一页、是否有下一页等
PageInfo<User> userPageInfo = new PageInfo<>(userList);

PageInfo{pageNum=1, pageSize=5, size=5, startRow=1, endRow=5, total=100, pages=20, list=Page{count=true, pageNum=1, pageSize=5, startRow=0, endRow=5, total=100, pages=20, reasonable=false, pageSizeZero=false}}

**注意:**只有紧跟着 PageHelper.startPage() 的那一句话起作用(原理可能是 PageHelper.startPage(pageNum,pageSize))在使用的时候启动了一个线程,致使了其能达到这个效果);

三、参数解析

4.1 PageHelper.startPage

方法调用

使用 PageHelper.startPage 静态方法调用 startPage:

特点:

  1. 静态方法,传递两个参数(当前页码,每页查询条数)

  2. 使用 pageHelper 分页的时候,不再关注分页语句,查询全部的语句

  3. 自动对 PageHelper.startPage 方法下的第一个 sql 查询进行分页 PageHelper.startPage(1,5);

    // 紧跟着的第一个 select 方法会被进行分页查询

也就是说在 Service 层 PageHelper.startPage(1,5);语句后一定是紧跟查询语句。

4.2 pageInfo
public class PageInfo<T> extends PageSerializable<T> {
    public static final int DEFAULT_NAVIGATE_PAGES = 8;
    // 当前页
    private int pageNum;
    // 每页的数量
    private int pageSize;
    // 当前页的数量
    private int size;
    // 下面两个不常用
    // 在页面中“显示 startRow” 到 endRow 共 size条数据
    // 当前页面中第一个元素的在数据库中的行号
    private long startRow;
    // 当前页面最后一个元素在数据库中的行号
    private long endRow;
    // 总页数
    private int pages;
    // 前一页
    private int prePage;
    // 下一页
    private int nextPage;
    // 是否为第一页
    private boolean isFirstPage;
    // 是否为最后一页
    private boolean isLastPage;
    // 是否有前一页
    private boolean hasPreviousPage;
    // 是否有下一页
    private boolean hasNextPage;
    // 导航页码数
    private int navigatePages;
    // 所有导航页号
    private int[] navigatepageNums;
    // 导航条上的第一页
    private int navigateFirstPage;
    // 导航条上的最后一页
    private int navigateLastPage;
    ......
}

学习参考:

[CSDN] https://blog.csdn.net/qq_37699336/article/details/113795004

[CSDN] https://zhuanlan.zhihu.com/p/344982068

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐