PageHelper分页查询规范说明
1. 规范目的
为统一项目中PageHelper分页查询的开发标准,规避分页异常、类型转换错误、查询逻辑混乱等问题,确保分页查询高效、稳定、可维护,明确分页查询的技术实现要求、参数规范、逻辑约束及异常处理,适用于项目中所有分页查询场景,同时适配SQL Server 2008 R2数据库及MyBatis-Plus框架。
2. 适用范围
本规范适用于项目中所有基于PageHelper的分页查询接口开发,包括但不限于操作日志、系统日志、业务日志、用户管理等模块的分页查询,涵盖多条件筛选、日期范围查询、分页参数控制等核心场景。
3. 核心技术依赖
-
分页组件:PageHelper(版本需与MyBatis-Plus兼容,避免版本冲突)
-
ORM框架:MyBatis-Plus(用于构建查询条件,避免硬编码SQL)
-
数据转换:自定义Bean转换工具(用于实体与响应VO的转换)
-
数据库:SQL Server 2008 R2(适配分页语法、日期类型处理)
4. 分页查询核心编写规范
4.1 分页参数规范
分页参数需统一封装,避免零散传递,参数定义及校验要求如下:
// 分页查询请求参数封装(必选)
public class PageQueryRequest {
// 页码(必填,默认1,最小值1)
@NotNull(message = "页码不能为空")
private Integer page = 1;
// 每页条数(必填,默认10,范围1-100)
@NotNull(message = "每页条数不能为空")
@Min(value = 1, message = "每页条数不能小于1")
@Max(value = 100, message = "每页条数不能超过100")
private Integer size = 10;
// 日期范围-开始时间(可选)
private LocalDateTime beginTime;
// 日期范围-结束时间(可选)
private LocalDateTime endTime;
// 其他业务查询参数(如日志类型、用户名等,按需添加)
}
说明:分页参数必须添加校验,防止非法参数(如页码为0、负数,每页条数超出范围)导致分页失效或报错。
4.2 分页初始化规范
分页初始化必须在查询操作之前执行,严格遵循“分页初始化→查询→结果处理”的顺序,禁止颠倒执行,避免分页失效。PageHelper提供两种常用分页写法,优先推荐简洁版Lambda写法,两种写法规范如下:
4.2.1 简洁版(推荐):Lambda表达式自动组装分页
// 1、启动分页 + 查询列表,自动组装,使用Lambda表达式(更简洁) PageInfo<Log> page = PageHelper.startPage(queryRequest.getPage(), queryRequest.getSize()) .doSelectPageInfo(() -> logMapper.selectList(wrapper));
写法总结:该写法将分页初始化与查询逻辑通过Lambda表达式绑定,PageHelper.startPage()初始化分页参数后,直接调用doSelectPageInfo()方法,传入查询逻辑(logMapper.selectList(wrapper)),自动执行分页查询并封装为PageInfo对象,无需手动创建PageInfo实例,代码更简洁、优雅,且能从根源避免分页逻辑与查询逻辑分离导致的异常,是项目中优先推荐的分页写法。核心优势的是:代码简洁、无冗余,分页与查询强绑定,减少手动操作,降低类型转换异常风险。
4.2.2 基础版:手动组装分页
// 1. 启用分页 PageHelper.startPage(queryRequest.getPage(), queryRequest.getSize()); // 2. 查询列表 List<Log> logs = logMapper.selectList(wrapper); // 3. 转换成分页,使用PageInfo包装查询结果 PageInfo<Log> page = new PageInfo<>(logs);
说明:该写法步骤清晰,适用于复杂查询场景(如多表关联、自定义SQL查询),需注意查询列表与分页初始化的顺序,禁止颠倒。
禁止写法:先执行查询,再调用PageHelper.startPage(),会导致分页不生效,返回全部数据。
4.3 分页查询逻辑规范
分页查询需包含“条件构建→分页初始化→查询执行→结果转换”四个核心步骤,结合推荐的Lambda简洁写法,完整逻辑如下:
// 步骤1:构建查询条件(MyBatis-Plus LambdaQueryWrapper) LambdaQueryWrapper<Log> wrapper = Wrappers.lambdaQuery(); // 绑定查询条件(如日志类型、IP、描述等,按需添加) wrapper.eq(StringUtils.isNotBlank(logType), Log::getLogType, logType) .like(StringUtils.isNotBlank(description), Log::getDescription, description) .between(Objects.nonNull(beginTime) && Objects.nonNull(endTime), Log::getCreateTime, beginTime, endTime) .orderByDesc(Log::getId); // 步骤2:分页初始化+查询执行(推荐Lambda简洁写法) PageInfo<Log> page = PageHelper.startPage(queryRequest.getPage(), queryRequest.getSize()) .doSelectPageInfo(() -> logMapper.selectList(wrapper)); // 步骤3:分页结果封装与VO转换 List<LogResponse> responseList = BeanConvertUtils.convertList(page.getList(), logConverter::toResponse);
4.4 分页结果处理规范
分页结果需通过PageInfo封装,禁止直接对VO列表进行强转,避免类型转换异常,核心要求如下:
-
原始查询结果通过PageInfo封装,获取总条数、当前页数据等分页信息,无论使用哪种分页写法,最终均需通过PageInfo获取分页相关数据;
-
VO转换需在PageInfo获取结果(page.getList())后执行,确保分页数据不丢失;
-
返回结果需包含“总条数、当前页数据”,格式统一为:
// 分页结果返回封装(标准格式)
public PageResult<LogResponse> getPageResult(PageInfo<Log> pageInfo) {
List<LogResponse> responseList = BeanConvertUtils.convertList(pageInfo.getList(), logConverter::toResponse);
return new PageResult<>(pageInfo.getTotal(), responseList);
}
5. 特殊场景处理规范
5.1 日期范围分页(重点)
当分页查询包含日期范围时,需先对日期参数进行处理,确保分页查询的时间范围准确,规范如下:
// 1. 处理前端传入的日期(LocalDate),转换为LocalDateTime
if (Objects.nonNull(dateBegin)) {
// 开始时间:当天00:00:00
beginTime = dateBegin.atStartOfDay();
}
if (Objects.nonNull(dateEnd)) {
// 结束时间:当天23:59:59.999
endTime = dateEnd.atTime(23, 59, 59, 999);
}
// 2. 绑定日期范围条件
wrapper.between(Objects.nonNull(beginTime) && Objects.nonNull(endTime),
Log::getCreateTime, beginTime, endTime);
5.2 分页异常处理规范
需捕获分页相关异常,避免因参数错误、数据库异常导致接口崩溃,规范写法:
try {
// 分页查询逻辑(推荐使用Lambda简洁写法)
PageInfo<Log> page = PageHelper.startPage(queryRequest.getPage(), queryRequest.getSize())
.doSelectPageInfo(() -> logMapper.selectList(wrapper));
} catch (ClassCastException e) {
// 处理类型转换异常(如Page强转失败)
log.error("分页查询类型转换异常:{}", e.getMessage());
throw new BusinessException("分页查询失败,请检查参数");
} catch (Exception e) {
log.error("分页查询异常:{}", e.getMessage());
throw new BusinessException("系统异常,分页查询失败");
}
6. 禁止事项(必遵循)
-
禁止先转换VO再进行分页强转,需先通过PageInfo封装原始查询结果,再转换VO;
-
禁止分页初始化在查询之后执行,否则分页失效,返回全部数据;
-
禁止不判空直接使用分页参数,需校验页码、每页条数的合法性;
-
禁止使用硬编码SQL进行分页,必须通过MyBatis-Plus + PageHelper实现,确保兼容性;
-
禁止忽略日期格式处理,避免因时间精度问题导致分页查询数据遗漏;
-
禁止在复杂查询场景中随意拆分分页与查询逻辑,优先使用Lambda简洁写法(doSelectPageInfo),减少异常风险。
7. 可复用性要求
分页查询逻辑需抽离为通用方法,可复用至所有分页场景,结合推荐的Lambda简洁写法,示例:
// 通用分页查询方法(可复用,推荐Lambda写法)
private <T> PageInfo<T> getPageResult(Integer page, Integer size, LambdaQueryWrapper<T> wrapper) {
return PageHelper.startPage(page, size)
.doSelectPageInfo(() -> logMapper.selectList(wrapper));
}
8. 验证标准
分页查询编写完成后,需满足以下验证条件,确保符合规范:
-
分页初始化正常,页码、每页条数生效,返回数据符合分页范围;
-
无ClassCastException、NullPointerException等分页相关异常;
-
分页总条数(total)准确,与数据库实际数据一致;
-
日期范围、多条件筛选与分页结合正常,无数据遗漏或错误;
-
优先使用Lambda简洁写法(doSelectPageInfo),代码无冗余、逻辑清晰。

803

被折叠的 条评论
为什么被折叠?



