-->

springboot实现查询语句的分页处理

1. 综述

springboot中实现分页的方法有很多,我大体上只看了3种,分别为mybatis-plus自带分页插件、hutool自带分页工具和pageheper实现分页,详细情况如下:

2. mybatis-plus实现分页

MyBatis-Plus 的分页插件 PaginationInnerInterceptor 提供了强大的分页功能,支持多种数据库,使得分页查询变得简单高效。

这是mp自带的分页插件,不过好像用的不多,我看了一下,主要是通过在启动类上面加注解扫描mapper文件包实现的这就要求所有的mapper必须在同一个包下且PaginationInnerInterceptor 仅用于数据库分页,并不能实现给个list分页

于mybatis-plus v3.5.9 起,PaginationInnerInterceptor 已分离出来。如需使用,则需单独引入 mybatis-plus-jsqlparser 依赖

image

如果你需要支持的数据库不在列表中,可以通过 Pull Request 请求添加。

添加分页配置插件:


@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
        // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
        return interceptor;
    }
}

配置文件可供配置属性介绍:
PaginationInnerInterceptor 提供了以下属性来定制分页行为:

属性名 类型 默认值 描述
overflow boolean false 溢出总页数后是否进行处理
maxLimit Long 单页分页条数限制
dbType DbType 数据库类型
dialect IDialect 方言实现类

建议单一数据库类型的均设置 dbType

自定义 Mapper 方法中使用分页

你可以通过以下方式在 Mapper 方法中使用分页:

IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
// 或者自定义分页类
MyPage selectPageVo(MyPage page);
// 或者返回 List
List<UserVo> selectPageVo(IPage<UserVo> page, Integer state);
对应的 XML 配置:
<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo">
    SELECT id,name FROM user WHERE state=#{state}
</select>

如果返回类型是 IPage,则入参的 IPage 不能为 null。如果想临时不分页,可以在初始化 IPage 时 size 参数传入小于 0 的值。 如果返回类型是 List,则入参的 IPage 可以为 null,但需要手动设置入参的 IPage.setRecords(返回的 List)。 如果 XML 需要从 page 里取值,需要使用 page.属性 获取。

我这里没有用上述方法,直接用的mybatis-plus自带的selectPage实现的分页查询

其他注意事项

  • 生成 countSql 时,如果 left join 的表不参与 where 条件,会将其优化掉。建议在任何带有 left join 的 SQL 中,都给表和字段加上别名。
  • 在使用多个插件时,请将分页插件放到插件执行链的最后面,以避免 COUNT SQL 执行不准确的问题。

Page 类

Page 类继承了 IPage 类,实现了简单分页模型。如果你需要实现自己的分页模型,可以继承 Page 类或实现 IPage 类。

属性名 类型 默认值 描述
records List emptyList 查询数据库列表
total Long 0 查询列表总记录数
size Long 10 每页显示条数,默认10
current Long 1 当前页
orders List emptyList 排序字段信息
optimizeCountSql boolean true 自动优化 COUNT SQL
optimizeJoinOfCountSql boolean true 自动优化 COUNT SQL 是否把 join 查询部分移除
searchCount boolean true 是否进行 count 查询
maxLimit Long 单页分页条数限制
countId String XML 自定义 count 查询的 statementId

这是mybatis-plus自带的Page类可以用来继承,分页使用,但是字段太多,也可以自己挑几个字段封装成新的Page类

由于分页了,所以数据量一般会很大,我们实现方法为分为了两个接口,第一个接口用于将分页数据同步到数据库,第二个就用来从数据库分页查询,关键点在于第一个同步到数据库会出现多线程操作数据,数据异常,加分布式锁还不能阻塞等待,那样查询时间会更慢,解决办法:创建ConcurrentHashMap<String, Boolean>和Map<String, List>,其中ConcurrentHashMap用于记录锁,Map<String, List>用于记录请求的msgid,每次调用同步数据库,用线程池提高速率,同时每个线程判断是否有锁,没锁正常操作,有锁将请求的msgid放进Map<String, List>,结束后通过websocket向所有msgid推送查询结束,也就是两个并发查询,都会进Map<String, List>,但只查询一次,最后推送两条websocket给前端

springboot中自带分页插件应用
mybatis-plus官网分页插件介绍

3. hutool分页工具类

hutool工具类中的分页类主要是返回分页所需的数组,如果要用需要自己建包装类,包装类的具体内容需要与前端协商好,这是我最初用的分页工具,用着还行吧,代码量有点大,虽然很基础

导入hutool工具类依赖

    implementation 'cn.hutool:hutool-all:5.8.10'

Mapper

    @Select("select * from busi_commission order by id limit #{countonepage} offset (#{pageno}-1) * #{countonepage}")
    List<Commmission> selectall(Integer pageno, Integer countonepage);

pageno:当前页数 countonepage:每页数据条数 displaycount分页所要展示的页数 下面都将是这样的意思
limit offset 不理解的可以看这个:菜鸟教材limit详解

Service

    public List<Commmission> selectall(Integer pageno, Integer countonepage){
        return commissionMapper.selectall(pageno, countonepage);
    }

ReturnResult包装类

点击查看代码
import lombok.Data;

@Data
public class ReturnResult {
    // 状态码
    private int code;
    // 消息
    private String msg;
    // 数据
    private Object data;

    private ReturnResult (){

    }

    private static ReturnResult buildResult(int code, String msg, Object data) {
        ReturnResult result = new ReturnResult();
        result.code = code;
        result.msg = msg;
        result.data = data;
        return result;
    }

    public static ReturnResult buildSuccessResult(String msg, Object data) {
        return buildResult(200, msg, data);
    }

    public static ReturnResult buildSuccessResult(Object data) {
        return buildSuccessResult("success", data);
    }

    public static ReturnResult buildFailureResult(int code, String msg, Object data) {
        return buildResult(code, msg, data);
    }

    public static ReturnResult buildFailureResult(String msg, Object data) {
        return buildFailureResult(500, msg, data);
    }

    public static ReturnResult buildFailureResult(String msg) {
        return buildFailureResult(500, msg, null);
    }
}

这个包装类是我们做项目所用,如果个人没需求可以不用,不过后面的Controller会用到

PageResult分页包装类

点击查看代码
import cn.hutool.core.util.PageUtil;
import lombok.Data;



@Data
public class PageResult {

    private Integer current_page;
    private Integer page_size;
    private Integer total;
    private Integer totalpage;
    private Object data;

    private int[] displaycount;

    public PageResult() {
    }



    public static PageResult buildPage(Integer current_page, Integer page_size, Integer total,Integer displaycount, Object data) {
        PageResult result = new PageResult();
        result.current_page = current_page;
        result.page_size = page_size;
        result.total = total;
        if (total % page_size != 0) {
            result.totalpage = total / page_size+1;
        }else {
            result.totalpage = total / page_size;
        }
        result.displaycount = PageUtil.rainbow(current_page, result.totalpage, displaycount);
        result.data = data;
        return result;
    }
}

Controller

    @GetMapping()
    public ReturnResult getAllCommission(Integer pageno,Integer countonepage,Integer displaycount){
        return ReturnResult.buildSuccessResult(buildPage(pageno,countonepage,commissionService.getcount(),displaycount,commissionService.selectall(pageno,countonepage)));
    }

hutool官网分页介绍:hutool官网分页工具类

这个工具类在PageResult中有用到

3. Pagehelper实现分页(SQL语句有注意事项)

Pagehelper是mybatis的,所以用它是需要写SQL语句的,是不能用mybtis-plus自动生成的,但是它使用更加简便

导入依赖

implementation 'com.github.pagehelper:pagehelper-spring-boot-starter:1.4.5'

Mapper

    @Select("select * from busi_commission order by id desc")
    List<Commmission> selectall();

这里加了个根据ID逆序排序
注意:这里的mapper中的SQL语句不能有分号,因为pageheper会调用两次SQL语句,第二次有limit,加分好limit加不进去,会报错

Service

public PageInfo<Commmission> selectall(Integer pageno, Integer countonepage) {
        PageHelper.startPage(pageno, countonepage);
        List<Commmission> result = commissionMapper.selectall();
        return new PageInfo<>(result);
    }

Controller

    @GetMapping()
    public ReturnResult getAllCommission(Integer pageno,Integer countonepage){
        return ReturnResult.buildSuccessResult(commissionService.selectall(pageno,countonepage));
    }
posted @ 2022-11-28 22:01  ꧁ʚ星月天空ɞ꧂  阅读(832)  评论(0)    收藏  举报