PageHelper 是一个非常流行的 MyBatis 分页插件,主要用于简化分页查询的实现。使用 PageHelper 可以在执行数据库查询时,自动处理分页参数,从而避免手动编写繁琐的分页逻辑。

今天就来学习一下PageHelper的相关知识和用法!

PageHelper

主要功能

  1. 分页查询:通过 PageHelper.startPage() 方法指定页码和每页的大小,之后执行的查询会自动分页。
  2. 排序功能:支持排序功能,分页查询时可以通过指定排序字段和排序方式来获得排序后的结果集。
  3. 简化分页逻辑:无需手动修改 SQL 语句,PageHelper 会自动为查询 SQL 添加分页逻辑,大大简化代码。
  4. 多数据库支持PageHelper 支持多种主流的数据库,如 MySQL、Oracle、PostgreSQL 等。

使用步骤

  1. 引入依赖

    pom.xml 中添加 PageHelper 依赖:

    <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
    </dependency>
  2. 配置拦截器

    在 MyBatis 配置文件或配置类中,注册 PageHelper 拦截器:

    @Bean
    public PageInterceptor pageHelper() {
    PageInterceptor pageInterceptor = new PageInterceptor();
    Properties properties = new Properties();
    properties.setProperty("helperDialect", "mysql"); // 数据库类型
    pageInterceptor.setProperties(properties);
    return pageInterceptor;
    }
  3. 分页查询使用示例

    在代码中使用 PageHelper.startPage() 方法来指定分页参数,后续的查询会自动带上分页信息:

    @Service
    public class UserService { @Autowired
    private UserMapper userMapper; public List<User> getUsers(int pageNum, int pageSize) {
    // 开启分页
    PageHelper.startPage(pageNum, pageSize);
    // 查询结果
    return userMapper.getAllUsers();
    }
    }
  4. 返回分页结果

    使用 PageInfo 来包装分页结果,包含分页信息和查询结果:

    List<User> userList = userMapper.getAllUsers();
    PageInfo<User> pageInfo = new PageInfo<>(userList);
    System.out.println(pageInfo.getTotal()); // 总记录数
    System.out.println(pageInfo.getList()); // 当前页的记录列表

核心方法

  • PageHelper.startPage(int pageNum, int pageSize):指定页码和每页大小,之后的查询会自动分页。
  • PageHelper.orderBy(String orderBy):设置排序规则,如 "id desc",按 id 倒序排列。
  • PageInfo<T>:封装分页结果信息,包含总记录数、总页数、当前页的记录等。

总结

PageHelper 提供了一种简洁的方式来实现 MyBatis 的分页查询,自动处理分页逻辑并简化代码,同时支持多种数据库和排序功能,是 MyBatis 用户进行分页查询的一个常用工具。

SpringBoot中的PageHelper

pagehelper-spring-boot-starterPageHelper 的 Spring Boot 自动配置版本,能够更简便地集成 PageHelper,特别是在 Spring Boot 项目中。相比于手动配置 PageHelper,使用 pagehelper-spring-boot-starter 可以进一步简化配置和使用过程。

使用步骤

  1. 引入依赖

    在 Spring Boot 项目的 pom.xml 中添加 pagehelper-spring-boot-starter 依赖:

    <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
    </dependency>
  2. 自动配置

    引入 pagehelper-spring-boot-starter 后,不需要手动配置 PageHelper 拦截器,Spring Boot 会自动配置好分页插件。

  3. 在查询方法中使用

    使用 PageHelper.startPage() 方法指定分页参数,在执行查询时,结果会自动分页。

    示例代码:

    @Service
    public class UserService { @Autowired
    private UserMapper userMapper; // 分页获取用户列表
    public PageInfo<User> getUsers(int pageNum, int pageSize) {
    // 设置分页参数
    PageHelper.startPage(pageNum, pageSize);
    // 执行查询,得到结果集
    List<User> users = userMapper.getAllUsers();
    // 使用PageInfo来封装分页信息
    return new PageInfo<>(users);
    }
    }
  4. 返回分页结果

    PageInfoPageHelper 提供的工具类,用于封装分页信息,如总记录数、总页数、当前页数据等。可以通过 PageInfo 对象获取到这些信息:

    PageInfo<User> pageInfo = userService.getUsers(1, 10);
    System.out.println(pageInfo.getTotal()); // 获取总记录数
    System.out.println(pageInfo.getPages()); // 获取总页数
    System.out.println(pageInfo.getList()); // 获取当前页的数据
  5. 自定义配置(可选)

    你可以通过 Spring Boot 的 application.propertiesapplication.yml 文件自定义 PageHelper 的相关配置,比如数据库方言、合理化配置、分页方式等。

    application.yml 中添加自定义配置:

    pagehelper:
    helper-dialect: mysql # 数据库方言
    reasonable: true # 启用合理化,避免页码超出范围
    support-methods-arguments: true # 支持分页参数作为方法参数
    params: count=countSql # 分页查询时统计总数的SQL

    或者在 application.properties 中:

    pagehelper.helperDialect=mysql
    pagehelper.reasonable=true
    pagehelper.supportMethodsArguments=true
    pagehelper.params=count=countSql

复杂度

  • 时间复杂度:分页查询的时间复杂度依赖于数据库查询操作。一般情况下,查询复杂度为 $O(n)$,加上分页条件,实际执行时可能会根据数据库的索引和优化机制有所不同。
  • 空间复杂度:空间复杂度取决于分页结果和数据的存储形式,一般为 $O(k)$,其中 k 是每页返回的数据量。

总结

通过 pagehelper-spring-boot-starter,在 Spring Boot 项目中可以轻松集成 PageHelper,自动完成分页查询的配置和操作,简化了开发者的代码量。同时还支持自定义配置,能够灵活应对各种分页需求。

实际运用

在我正在写的仿12306项目中很多地方都会用到pagehelper,所以一般会封装分页查询的入参和出参类,就以查询乘车人为例:

PageReq

封装PageReq作为分页查询入参类的父类,为分页查询提供pageNumpageSize

PageReq
public class PageReq {

    @NotNull(message = "【页码】不能为空")
private Integer start; @NotNull(message = "【每页条数】不能为空")
@Max(value = 100, message = "【每页条数】不能超过100")
private Integer count; public @NotNull(message = "【页码】不能为空") Integer getStart() {
return start;
} public void setStart(@NotNull(message = "【页码】不能为空") Integer start) {
this.start = start;
} public @NotNull(message = "【每页条数】不能为空") @Max(value = 100, message = "【每页条数】不能超过100") Integer getCount() {
return count;
} public void setCount(@NotNull(message = "【每页条数】不能为空") @Max(value = 100, message = "【每页条数】不能超过100") Integer count) {
this.count = count;
} @Override
public String toString() {
final StringBuffer sb = new StringBuffer("pageReq{");
sb.append("start=").append(start);
sb.append(", count=").append(count);
sb.append('}');
return sb.toString();
}
}

查询乘车人服务的入参类继承PageReq类;

PassengerQueryReq
public class PassengerQueryReq extends PageReq {

    private Long memberId;

    private String idCard;

    public Long getMemberId() {
return memberId;
} public void setMemberId(Long memberId) {
this.memberId = memberId;
} public String getIdCard() {
return idCard;
} public void setIdCard(String idCard) {
this.idCard = idCard;
} @Override
public String toString() {
final StringBuffer sb = new StringBuffer("PassengerQueryReq{");
sb.append("memberId=").append(memberId);
sb.append(", idCard='").append(idCard).append('\'');
sb.append('}');
return sb.toString();
}
}

在查询乘车人服务中使用PageReq提供的pageNumpageSize调用PageHelper

PassengerService
@Service
public class PassengerService { @Resource
private PassengerMapper passengerMapper; public List<PassengerQueryResp> queryList (PassengerQueryReq req) {
PassengerExample passengerExample = new PassengerExample();
PassengerExample.Criteria criteria = passengerExample.createCriteria();
if (ObjectUtil.isNotNull(req.getMemberId())) {
criteria.andMemberIdEqualTo(req.getMemberId());
}
PageHelper.startPage(req.getStart(), req.getCount());
List<Passenger> passengerList = passengerMapper.selectByExample(passengerExample);
return BeanUtil.copyToList(passengerList, PassengerQueryResp.class);
} public void update(PassengerSaveReq req) {
DateTime now = DateTime.now();
Passenger passenger = BeanUtil.copyProperties(req, Passenger.class);
passenger.setMemberId(LoginMemberContext.getId());
passenger.setModifiedTime(now); PassengerExample passengerExample = new PassengerExample();
passengerExample.createCriteria().
andMemberIdEqualTo(passenger.getMemberId()).
andIdCardEqualTo(passenger.getIdCard()); passengerMapper.updateByExampleSelective(passenger, passengerExample);
}
}

PageResp

封装PageResp作为response类,返回查询总数、分页总数和查询列表;

PageResp
public class PageResp<T> implements Serializable {

    private static final Long serialVersionUID = 1L;

    /**
* 查询结果总数
*/
private Long total; /**
* 查询结果列表
*/
private List<T> list; public List<T> getList() {
return list;
} public void setList(List<T> list) {
this.list = list;
} public Long getTotal() {
return total;
} public void setTotal(Long total) {
this.total = total;
} @Override
public String toString() {
final StringBuffer sb = new StringBuffer("PageResp{");
sb.append("total=").append(total);
sb.append(", list=").append(list);
sb.append('}');
return sb.toString();
}
}

查询乘车人服务中使用PageInfo获取分页查询的结果总数和分页数,返回PageResp

PassengerService
@Service
public class PassengerService { private static final Logger LOG = LoggerFactory.getLogger(PassengerService.class); @Resource
private PassengerMapper passengerMapper; public PageResp<PassengerQueryResp> queryList (PassengerQueryReq req) {
PassengerExample passengerExample = new PassengerExample();
PassengerExample.Criteria criteria = passengerExample.createCriteria();
if (ObjectUtil.isNotNull(req.getMemberId())) {
criteria.andMemberIdEqualTo(req.getMemberId());
} // mybatis PageHelper分页查询
LOG.info("查询页码:{}", req.getStart());
LOG.info("每页条数:{}", req.getCount());
PageHelper.startPage(req.getStart(), req.getCount());
List<Passenger> passengerList = passengerMapper.selectByExample(passengerExample);
// 把passengerList转为passengerQueryRespList
List<PassengerQueryResp> passengerQueryResp = BeanUtil.copyToList(passengerList, PassengerQueryResp.class); // pageHelper获取分页查询总条数,将分页查询结果(条数+list)封装到pageResp
PageInfo<Passenger> pageInfo = new PageInfo<>(passengerList);
LOG.info("总条数:{}", pageInfo.getTotal());
LOG.info("总页数:{}", pageInfo.getPages());
PageResp<PassengerQueryResp> pageResp = new PageResp<>();
pageResp.setList(passengerQueryResp);
pageResp.setTotal(pageInfo.getTotal());
return pageResp;
}
}

PageHeper的更多相关文章

  1. Mybaits-plus实战(二)

    1. Mybaits-plus实战(二) 1.1. mybatis-plus插件 1.1.1. 用法 先举个例子介绍用法,如下:直接作为Bean注入,一般来讲插件太多印象性能,所以大部分插件都只在测试 ...

  2. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_2-5.开源工具的优缺点选择和抽象方法的建议

    笔记 5.开源工具的优缺点选择和抽象方法的建议     简介:讲解开源工具的好处和弊端,如pageHeper分页拦截器,tk自动生成工具,抽象方法的利弊等 1.开源工具             好处: ...

  3. Mybatis-plus 思维导图,让 Mybatis-plus 不再难懂

    摘要: Mybatis-Plus(简称MP)是一个Mybatis的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发.提高效率而生. mybatis-plus与mybatis myba ...

  4. mybatis-plus思维导图,让mybatis-plus不再难懂

    mybatis-plus与mybatis mybatis Mybatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置 ...

随机推荐

  1. yb课堂 新版Vue+脚手架Vue-Cli 4.3安装 《二十七》

    本地搭建Vue.CLI.Cube-UI相关框架 什么是Vue 一套用于构建用户界面的渐进式框架.与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用.Vue的核心库只关注视图层,不仅易于上手,还 ...

  2. Mysql密码安全策略修改

    Mysql5.7默认有密码安全策略,密码安全级别要求比较高,在测试环境中使用起来不方便,本经验将介绍如何修改Mysql的密码安全策略,解决ERROR 1819错误. 1:首先使用root用户连接mys ...

  3. Windows11下使用VcXsrv+xfce4实现图形化窗口

    通过 sudo apt-get install xfce4-terminal sudo apt-get install xfce4 sudo service dbus restart 来安装所需要的软 ...

  4. Charles抓包配置、常见问题和解决方法

    1.下载安装charles,官方下载地址:https://www.charlesproxy.com/download/ 如图,下载所对应系统需要的相应版本即可. 2.解压Charles包,双击Char ...

  5. 【Java】Collection子接口:其二 Set 组接口

    Collection子接口:其二 Set 组接口 - Set接口是Collection的子接口,Set没有提供额外的方法 - Set集合中不允许包含重复的元素,如果重复添加,只保留最新添加的那一个 - ...

  6. 【Hibernate】Re01.6 HQL

    一.支持的查询方式 Hibernate的查询支持三种方式: 1.HQL查询 2.Criteria查询 3.NativeSQL 原生SQL查询 二.HQL查询语言 全称 Hibernate Query ...

  7. 【FastDFS】环境搭建 02 测试

    自带工具测试: 编辑客户端配置文件: vim client.conf 配置完成后,随便上传一个图片到root目录下 运行FastFDS文件上传程序,并将客户端配置文件作为加载参数1,要上传的图片文件位 ...

  8. GPG公钥的删除与注销

    参考: 如何在 Gitee 上使用 GPG 我们通过在本地主机保存GPG私钥,然后在Gitee或Github上保存GPG公钥的方式来实现对git的commit和tag操作的签名. 当GPG公私秘钥对作 ...

  9. 强化学习:AC算法中为什么不使用Q函数来表示优势函数

    强化学习中的策略梯度法(PG)不直接使用Q函数作为值函数来进行计算已经在Sutton的PG公式证明中提出,主要作用就是减少方差,因此使用优势函数进行计算.作为PG算法类中最常见的AC类算法有着较多的使 ...

  10. 【转载】 Pytorch手动释放显存

    原文地址: http://www.shijinglei.com/2020/04/20/pytorch%E9%87%8A%E6%94%BE%E6%98%BE%E5%AD%98/ ============ ...