PageHelper实现分页查询
前端发送的请求参数
后端返回的对象类型
Controller类实现
/*** 员工分页查询* @param employeePageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("员工分页查询")public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){log.info("员工分页查询,参数为:{}",employeePageQueryDTO);PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);return Result.success(pageResult);}
Service类实现
/*** 分页查询* @param employeePageQueryDTO* @return*/public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO){//select * from employee limit 0,10//MyBatis提供的插件PageHelper:动态在SQL语句中拼接limit,动态计算//开始分页查询(传页码与每页记录数)PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());//startPage()方法底层是通过ThreadLocal实现的//此插件规定返回值必须是Page,注意:import com.github.pagehelper.Page;Page<Employee> page = (Page<Employee>) employeeMapper.pageQuery(employeePageQueryDTO);long total = page.getTotal();List<Employee> records = page.getResult();return new PageResult(total,records);}
PageHelper插件依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.3.0</version></dependency>
Mapper接口实现
/*** 分页查询* @param employeePageQueryDTO* @return*///动态SQL一般不用注解方式书写,通常采用xml配置文件书写//注意:import com.github.pagehelper.Page;Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
Mapper.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.sky.mapper.EmployeeMapper">//模糊查询中{name != ''}不能有空格,否则会报500错误<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>//PageHelper插件已经拼接了limit//根据创建时间进行降序order by create_time desc</select>
</mapper>
application.yml配置mybatis
mybatis:# mapper配置文件mapper-locations: classpath:mapper/*.xml # 指定MyBatis映射文件的位置,扫描resources/mapper目录下的所有XML文件,这些文件包含 SQL 映射语句。type-aliases-package: com.sky.entity # 指定一个或多个包,MyBatis会在这些包中查找类并生成别名configuration:# 开启驼峰命名map-underscore-to-camel-case: true # 当开启此选项后,将数据库中下划线命名字段自动映射为Java中的驼峰命名,例:MyBatis 会自动将数据库中下划线命名的字段(如 user_name)映射到 Java 中的驼峰命名(如 userName)。pagehelper:helperDialect: mysql # 告诉 PageHelper 如何生成符合特定数据库语法的分页 SQL 查询#常见的方言选项:#mysql: MySQL 数据库#oracle: Oracle 数据库#postgresql: PostgreSQL 数据库#sqlserver: SQL Server 数据库#sqlite: SQLite 数据库
安装MyBatisX插件
File——>Settings——>Plugins
PageHelper详解及startPage()方法的底层实现
PageHelper 是一个用于 MyBatis 的插件,主要功能是帮助进行分页查询。它通过拦截器的方式,对数据库的查询进行处理,从而实现高效的分页功能。
PageHelper.startPage()
方法的底层实现主要依赖于 MyBatis 的 SQL 拦截器机制。以下是其基本的工作原理和实现步骤:
1. 拦截器机制
- MyBatis 拦截器:MyBatis 允许开发者通过拦截器在执行 SQL 之前或之后进行自定义处理。PageHelper 利用这个特性来插入分页逻辑。
2. 工作流程
2.1 调用 startPage()
当你调用 PageHelper.startPage(pageNum, pageSize)
时,PageHelper 会:
- 设置分页信息:将当前的页码和每页的记录数存储在一个 ThreadLocal 变量中。这使得这些信息可以在整个线程中共享,而不需要显式地传递。
PageInfo pageInfo = new PageInfo();
pageInfo.setPageNum(pageNum);
pageInfo.setPageSize(pageSize);
ThreadLocalHolder.setPageInfo(pageInfo); // 保存到 ThreadLocal
2.2 执行 SQL 查询
接下来,当 MyBatis 执行查询操作时,PageHelper 的拦截器会被触发:
-
拦截查询:拦截器捕捉到
Statement
或Executor
的执行方法(如query
方法)。 -
修改 SQL:在拦截器中,PageHelper 会根据传入的页码和页大小,计算出
LIMIT
和OFFSET
的值,进而修改原始 SQL 查询语句。
String originalSql = invocation.proceed(); // 获取原始 SQL
String paginatedSql = modifySqlForPagination(originalSql, pageNum, pageSize); // 修改 SQL
3. SQL 修改
- 构建分页 SQL:根据数据库的不同类型,生成适合该数据库的分页 SQL。例如,对于 MySQL,可能会使用
LIMIT #{offset}, #{pageSize}
。
4. 执行修改后的 SQL
- 执行新的 SQL:执行修改后的 SQL 查询,并获取结果集。
5. 返回分页结果
- 计算总记录数:在执行分页查询时,PageHelper 还会自动查询总记录数,以便在返回时提供完整的分页信息。
6. 封装结果
最后,PageHelper 会将结果封装到 PageInfo
对象中,方便开发者获取分页相关的信息,如总记录数、当前页的数据等。
总结
通过 MyBatis 的拦截器机制,PageHelper 能够轻松地在查询过程中插入分页逻辑,而无需用户手动修改 SQL。这样使得分页变得更加简单和高效,同时也保持了代码的整洁性。