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. 解决方案 | 预装win11如何退回win10?

    0.定义 本文所说的[退回]并不指的是win10升级后的变成win11再变为win10的退回.退回应该理解为[降级],或者叫作返回上一个版本.本文的适用范围局限于,预装系统是win11,想要不通过u盘 ...

  2. C# 对象复制三种方法效率对比——反射、序列化、表达式树

    1.需求 在代码中经常会遇到需要把对象复制一遍,或者把属性名相同的值复制一遍. 比如: public class Student { public int Id { get; set; } publi ...

  3. STM32开发环境配置记录——关于PlatformIO + VSCode + CubeMX的集成环境配置

    前言 ​ 为什么配置这样的一个环境呢?鄙人受够了Keil5那个简陋的工作环境了,实在是用不下去,调试上很容易跟CubeMX的代码产生不协调导致调试--发布代码不一致造成的一系列问题.CubeIDE虽说 ...

  4. java web 开发框架编

    学习web 框架上开发需要的是安装  mysql 8.0  idea 2022 git  2.2.23  node 16以上 (新版本不好拉有些库了)jdk 最好是17以上 jdk8也是行的,反正不管 ...

  5. NameCheap域名怎么样,如何注册购买域名?如何解析域名?

    Namecheap介绍 Namecheap是一家国外域名注册商和网站托管公司,成立于2000年,提供域名注册.虚拟主机.电子邮件托管.SSL证书.免费的WHOIS保护.CDN.VPS主机和独立服务器. ...

  6. python 私有属性的作用

    python 私有属性的作用 class Player(): def __init__(self, name, power, skill): self.name = name self.power = ...

  7. Jmeter函数助手3-RandomString

    RandomString函数用于生成指定内容范围的指定长度随机字符. Random string length:限制生成的长度,比如输入6则会生成6位字符 Chars to use for rando ...

  8. .NET8 Blazor 从入门到精通:(一)关键概念

    目录 Blazor 的关键概念 项目模板 Razor 语法 依赖注入 注入配置 HeadOutlet 组件 @code 分离 Blazor 调试 CSS 隔离 调用JavaScript 最近在学习 B ...

  9. 什么是web3 为什么web3很重要

    中心化网络已经帮助数十亿人融入了互联网,并在其上创建了稳定.可靠的基础设施. 与此同时,少数中心化巨头几乎垄断了互联网,甚至可以为所欲为. Web3 是摆脱这一困境的方案. 不同于科技巨头垄断的传统互 ...

  10. 【Scala】05 对象特性Part2

    特质重复继承关系 父类特质 A 子类特质B 继承 A 子类特质C 继承A 类D 继承了 B 又实现了 C class D extends B with C 继承顺序是 D 继承 C 继承 B 继承 A ...