前端发送的请求参数
后端返回的对象类型
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。这样使得分页变得更加简单和高效,同时也保持了代码的整洁性。