在之前的单体项目中也好,微服务项目中也罢,对于分页查询我一直比较模糊,这次在第二个项目中再一次用到了分页查询,我就简单总结一下两个微服务项目中的分页查询的差异和共同。

项目背景:

在原先的慧径学习系统(微服务项目)中,有这样的一个用户服务:

@Override
public Page<UserDetail> queryUserDetailByPage(UserPageQuery query, UserType type) {
    // 1.分页条件
    Page<UserDetail> p = query.toMpPageDefaultSortByCreateTimeDesc();
    // 2.搜索条件
    Integer status = query.getStatus();
    String name = query.getName();
    String phone = query.getPhone();
    QueryWrapper<UserDetail> wrapper = new QueryWrapper<>();
    wrapper
            .eq(type != null , "u.type", type)
            .eq(status != null, "u.status", status)
            .eq(StringUtils.isNotBlank(phone),"u.cell_phone", phone)
            .like(StringUtils.isNotBlank(name), "ud.name", name);
    // 3.查询
    p = getBaseMapper().queryByPage(p, wrapper);
    // 4.返回
    return p;
}
@Data
@ApiModel(description = "分页请求参数")
@Accessors(chain = true)
public class PageQuery {
    public static final Integer DEFAULT_PAGE_SIZE = 20;
    public static final Integer DEFAULT_PAGE_NUM = 1;

    @ApiModelProperty(value = "页码", example = "1")
    @Min(value = 1, message = "页码不能小于1")
    private Integer pageNo = DEFAULT_PAGE_NUM;

    @ApiModelProperty(value = "每页大小", example = "5")
    @Min(value = 1, message = "每页查询数量不能小于1")
    private Integer pageSize = DEFAULT_PAGE_SIZE;

    @ApiModelProperty(value = "是否升序", example = "true")
    private Boolean isAsc = true;

    @ApiModelProperty(value = "排序字段", example = "id")
    private String sortBy;
    
    // ...
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "分页结果")
public class PageDTO<T> {
    @ApiModelProperty("总条数")
    protected Long total;
    @ApiModelProperty("总页码数")
    protected Long pages;
    @ApiModelProperty("当前页数据")
    protected List<T> list;
    
    // 提供了多种静态方法来创建PageDTO对象
    public static <T> PageDTO<T> of(Page<T> page) { ... }
    public static <T,R> PageDTO<T> of(Page<R> page, Function<R, T> mapper) { ... }
    public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz) { ... }
    // ...
}

在这里的分页查询实现服务中可以发现:

1.首先从参数中分离得到分页条件(页码,每页大小等)

2.其次从参数中分离得到对数据的搜索条件(用户状态,名字等)

3.调用queryByPage()方法进行分页查询,参数类型为Page<T>和QueryWrapper

而在目前的云图库项目中,用户服务中的分页查询是这样实现的:

@PostMapping("/list/page/vo")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<UserVO>> listUserVOByPage(@RequestBody UserQueryRequest userQueryRequest) {
        ThrowUtils.throwIf(userQueryRequest == null, ErrorCode.PARAMS_ERROR);

        long current = userQueryRequest.getCurrent();
        long pageSize = userQueryRequest.getPageSize();


        //userService.page(分页对象,查询条件包装器)
        Page<User> userPage = userService.page(new Page<>(current, pageSize), userService.getQueryWrapper(userQueryRequest));

        // 转换为VO列表
        Page<UserVO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserVO> userVOList = userService.getUserVOList(userPage.getRecords());
        userVOPage.setRecords(userVOList);

        return ResultUtils.success(userVOPage);
    }

在这里的分页查询实现服务中可以发现:

1.首先从参数中分离得到分页条件(页码,每页大小等)

2.其次从参数中分离得到对数据的搜索条件(用户状态,名字等)

3.调用userService()方法进行分页查询,参数类型为Page<T>和QueryWrapper

差异:

1. 实现方式不同

云图库项目使用 MyBatis-Plus 提供的 IService 接口中的 page() 方法实现的分页查询。它直接在 Service 层调用,使用了 MyBatis-Plus 的自动分页功能。


getBaseMapper().queryByPage() 方法: 这是一种自定义的分页查询方式,需要在 Mapper 接口中定义 queryByPage 方法,并在对应的 XML 文件中编写 SQL 语句来实现分页查询。

2. 灵活性不同


代码中的分页查询方法:
①使用 MyBatis-Plus 内置分页,自动在原始查询 SQL 基础上添加分页逻辑
②通过 QueryWrapper 构造查询条件,使用链式调用,代码简洁
③不需要编写额外的 SQL 语句


getBaseMapper().queryByPage() 方法:
①需要手动编写 SQL 语句,可以实现更复杂的分页逻辑
②可以针对特殊需求定制分页查询
③更加灵活,但需要更多的代码量

3. 性能和效率


①MyBatis-Plus 会对查询进行优化,自动处理分页逻辑
②对于简单的分页查询,性能表现良好
③在数据量特别大时,可能不如手写 SQL 精确控制


getBaseMapper().queryByPage() 方法:
①可以通过手写 SQL 优化查询性能
②可以使用数据库特有的分页语法(如 MySQL 的 LIMIT,Oracle 的 ROWNUM)
③在复杂查询场景下可能有更好的性能表现

总结

云图库项目中使用的是 MyBatis-Plus 提供的分页查询方式,这种方式简单易用,适合大多数场景。而 getBaseMapper().queryByPage() 是一种更自定义的分页方式,适合需要特殊优化或复杂查询的场景。
在实际开发中,如果项目中已经使用了 MyBatis-Plus,建议继续使用其提供的分页功能;只有在需要特殊优化或框架功能无法满足需求时,才考虑使用自定义的分页方法。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐