springboot项目中分页查询的使用示例解析

2025-05-14 05:08:47 163
魁首哥

spring boot 分页查询详解

本文详细讲解 spring boot 中两种主流分页方案:mybatis + pagehelpermybatis plus的实现方式、原理、优缺点及实际应用场景。内容涵盖配置、代码示例、注意事项和对比总结。

一、分页查询概述

分页查询是 web 开发中处理大数据集的核心需求,其本质是按需加载数据,避免一次性返回全部数据导致的性能问题。实现方式通常分为两类:

  • 物理分页:通过 sql 直接限制查询范围(如limit)。
  • 逻辑分页:先查询全量数据,再在内存中截取分页(不推荐)。

spring boot 中常用物理分页,依赖 mybatis 的插件机制动态修改 sql。

二、mybatis + pagehelper 分页方案

1. 核心依赖


    com.github.pagehelper
    pagehelper-spring-boot-starter
    1.4.6

2. 配置参数(application.yml)

pagehelper:
  helper-dialect: mysql       # 指定数据库方言(mysql/oracle/postgresql)
  reasonable: true            # 合理化分页参数(超出范围时自动修正)
  support-methods-arguments: true  # 支持接口参数传递分页

3. 分页实现代码

service 层

public pageinfo getusersbypage(int pagenum, int pagesize) {
    try {
        // 开启分页:对紧接的第一个查询生效
        pagehelper.startpage(pagenum, pagesize);
        list users = usermapper.selectall();
        return new pageinfo<>(users);  // 包含总条数、总页数等信息
    } finally {
        pagehelper.clearpage();  // 清理 threadlocal
    }
}

mapper 接口

@select("select * from user where status = 1")
list selectall();

4. 分页原理

  • threadlocal 传递参数pagehelper.startpage()将分页参数存入当前线程的threadlocal
  • 拦截器重写 sql:mybatis 拦截器自动拼接limit offset, pagesize
  • 自动执行 count 查询:生成分页数据后,自动查询总记录数。

5. 注意事项

  • 调用顺序startpage()必须紧贴查询方法,否则分页不生效。
  • 线程安全:异步或多线程场景需手动传递分页参数。
  • 性能优化:复杂 sql 可自定义 count 查询:
@select("select count(*) from user where status = 1")
long countusers();
// 指定自定义 count 方法
pagehelper.startpage(1, 10).count(true).setcountsql("countusers");

三、mybatis plus 分页方案

1. 核心依赖


    com.baomidou
    mybatis-plus-boot-starter
    3.5.3.1

2. 分页插件配置

@configuration
public class mybatisplusconfig {
    @bean
    public mybatisplusinterceptor mybatisplusinterceptor() {
        mybatisplusinterceptor interceptor = new mybatisplusinterceptor();
        // 添加分页拦截器,指定数据库类型
        interceptor.addinnerinterceptor(new paginationinnerinterceptor(dbtype.mysql));
        return interceptor;
    }
}

3. 分页实现代码

service 层

public ipage getusersbypage(int pagenum, int pagesize) {
    // 创建分页对象
    page page = new page<>(pagenum, pagesize);
    // 执行分页查询(自动处理 sql)
    return usermapper.selectpage(page, new querywrapper().eq("status", 1));
}

mapper 接口

public interface usermapper extends basemapper {
    // 继承 basemapper 默认提供分页方法
}

4. 分页原理

  • 内置分页拦截器:自动识别ipage参数,重写 sql。
  • 统一分页模型:通过ipage接口封装分页参数和结果。
  • 多数据库支持:根据dbtype生成不同分页 sql(如 oracle 的 rownum)。

5. 注意事项

  • wrapper 条件:分页需结合querywrapper或自定义 sql。
  • 性能优化:大数据量分页需手动优化 count 查询:
// 关闭自动 count 查询
page page = new page<>(pagenum, pagesize, false);
list users = usermapper.selectpage(page, wrapper);
// 手动执行 count 查询
page.settotal(usermapper.selectcount(wrapper));

四、对比总结

对比维度mybatis + pagehelpermybatis plus
依赖复杂度仅需 pagehelper 依赖需引入 mybatis plus 全家桶
配置难度需配置方言、合理化参数仅需定义分页拦截器
侵入性低(无需修改 mapper)高(需继承 basemapper
sql 灵活性支持任意复杂 sql,手动优化空间大简单查询高效,复杂 sql 需自定义
线程安全依赖 threadlocal,需注意异步场景无线程安全问题(参数传递)
适用场景已有 mybatis 项目,需灵活分页新项目或深度集成 mybatis plus

五、最佳实践与常见问题

1. 最佳实践

  • 简单分页:优先使用 mybatis plus,减少代码量。
  • 复杂 sql:选择 pagehelper,灵活控制 sql。
  • 性能优化
    • 添加索引(如create index idx_status on user(status))。
    • 避免select *,仅查询必要字段。
    • 大数据量分页使用游标分页延迟关联

2. 常见问题

q1:分页不生效

  • 原因startpage()调用顺序错误或未配置拦截器。
  • 解决:确保startpage()在查询方法前调用,检查依赖和配置。

q2:总条数(total)为 0

  • 原因:count 查询未匹配条件或 sql 错误。
  • 解决:手动指定 count 方法或检查查询条件。

q3:性能低下

优化

-- 原始 sql(性能差)
select * from orders order by id limit 1000000, 10;
-- 优化 sql(延迟关联)
select * from orders 
where id >= (select id from orders order by id limit 1000000, 1)
order by id limit 10;

六、附录:完整代码示例

pagehelper 完整示例

// service
public pageinfo getusers(int pagenum, int pagesize) {
    try {
        pagehelper.startpage(pagenum, pagesize);
        list users = usermapper.selectbycondition("active");
        return new pageinfo<>(users);
    } finally {
        pagehelper.clearpage();
    }
}
// mapper
@select("select * from user where status = #{status}")
list selectbycondition(string status);

mybatis plus 完整示例

// service
public ipage getusers(int pagenum, int pagesize) {
    page page = new page<>(pagenum, pagesize);
    querywrapper wrapper = new querywrapper<>();
    wrapper.eq("status", "active");
    return usermapper.selectpage(page, wrapper);
}

到此这篇关于springboot项目中分页查询的使用解析的文章就介绍到这了,更多相关springboot分页查询使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

分享
海报
163
上一篇:Java常见运算符之位运算符大全 下一篇:Java Javassist轻松操作字节码的技术指南

忘记密码?

图形验证码