专栏名称: Java专栏
一个Java、Python、数据库、中间件、业内资讯、面试、学习资源等干货的知识分享社区。
目录
相关文章推荐
51好读  ›  专栏  ›  Java专栏

Spring Boot + PageHelper 实现分页,总结得很全了!

Java专栏  · 公众号  ·  · 2020-11-05 12:20

正文

双11了,服务器限时限量秒杀

1核2G,1年62元,3年200元,限时秒杀

1核2G,1年62元,3年200元,限时秒杀

1核2G,1年62元,3年200元,限时秒杀


CSDN:https://blog.csdn.net/NOT_TWO_CHEN/

简书:https://www.jianshu.com/p/a24a9ff323c9

一. 开发准备

1. 开发工具

2. 开发环境

3. 开发依赖

<dependency>
 <groupId>org.springframework.bootgroupId>
 <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
 <groupId>org.mybatis.spring.bootgroupId>
 <artifactId>mybatis-spring-boot-starterartifactId>
 <version>2.1.3version>
dependency>
  • PageHelper
<dependency>
 <groupId>com.github.pagehelpergroupId>
 <artifactId>pagehelper-spring-boot-starterartifactId>
 <version>1.3.0version>
dependency>

二. 技术文档

1. 基于SpringBoot

2. 基于MyBatis

3. 集成PageHelper

  • PageHelper 开源仓库:https://github.com/pagehelper/Mybatis-PageHelper


Spring Boot 学习理论和实战推荐:
https://github.com/javastacks/spring-boot-best-practice

三. 应用讲解

1. 基本使用

在实际项目运用中, PageHelper 的使用非常便利快捷,仅通过 PageInfo + PageHelper 两个类,就足以完成分页功能,然而往往这种最简单的集成使用方式,却在很多实际应用场景中,没有得到充分的开发利用.

接下来是我们最常见的使用方式:

public PageInfo page(RequestParamDto param) {
 PageHelper.startPage(param.getPageNum(), param.getPageSize());
 List list = mapper.selectManySelective(param);
 PageInfo pageInfo = (PageInfo)list;
 return pageInfo;

在某种程度上而言,上述写法的确是符合PageHelper的使用规范 :

 在集合查询前使用`PageHelper.startPage(pageNum,pageSize)`,并且*中间不能穿插执行其他SQL*

但是作为Developer的我们,往往只有在追求完美和极致的道路上才能够寻得突破和机遇; 以下是合理且规范的基本使用:

public PageInfo page(RequestParamDto param) {
 return PageHelper.startPage(param.getPageNum(), param.getPageSize())
     .doSelectPageInfo(() -> list(param))

public List list(RequestParamDto param) {
 return mapper.selectManySelective(param);
}

FAQ

1. 为什么要重新声明一个list函数?

答: 往往在很多实际业务应用场景中, 分页查询 是基于大数据量的表格展示需求来进行的. 然而很多时候, 譬如 : 内部服务的互相调用, OpenAPI 的提供.

甚至在某些前后端分离联调的业务场景中,是同样需要一个非分页集合查询接口来提供服务的. 另外,暂时以上因素抛开不谈,我们可以根据上述写法来定义和规范某些东西

譬如 : 分页和集合查询的 分离和解耦 (解耦详情请看进阶使用), 分页请求的请求和响应与实际业务 参数的分离 (详情请看进阶使用)等等...

2. doSelectPageInfo 是什么?

答: doSelectPageInfo PageHelper.startPage() 函数返回的默认 Page 实例内置的函数,该函数可以用以 Lambda 的形式通过额外的 Function 来进行查询而不需要再进行多余的 PageInfo List 转换,而 doSelectPageInfo 的参数则是 PageHelper 内置的 Function(ISelect) 接口用以达到转换 PageInfo 的目的

3. 这种写法的代码量看起来不少反多?

答: 正如同①中所描述的,就代码量而言,确实没有更进一步的简化,但是再某些业务场景中,在已具有 list 函数接口的情况下,是一种更直观的优化(优化详情请看进阶使用)

2. 进阶使用

先看代码,再谈解析:

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import java.util.List;

/**
 * @param  泛型request
 * @param  泛型response
 */

public interface BaseService<ParamResult{

    /**
     * 分页查询
     *
     * @param param 请求参数DTO
     * @return 分页集合
     */

    default PageInfo page(PageParam param) {
        return PageHelper.startPage(param).doSelectPageInfo(() -> list(param.getParam()));
    }

    /**
     * 集合查询
     *
     * @param param 查询参数
     * @return 查询响应
     */

    List list(Param param);
}

可以看到 BaseService 可以作为全局 Service 通用接口的封装和声明,而作为通用分页接口page函数却在此处利用 interface 特有关键字 default 直接声明了 page 函数的方法体 body

import com.github.pagehelper.IPage;
import lombok.Data;
import lombok.experimental.Accessors;

@Data // 为省略冗余代码使用lombok 实际应有常规Getter/Setter Construction toString等
@Accessors(chain = true// 此lombok注解是为了实现 Entity伪Build 譬如: entity.setX(x).setY(y)
public class PageParam<T>  implements IPage {

    //  description = "页码", defaultValue =  1
    private Integer pageNum = 1;

    // description = "页数", defaultValue = 20
    private Integer pageSize = 20;

    // description = "排序", example = "id desc"
    private String orderBy;

    //  description = "参数"
    private T param;

    public PageParam setOrderBy(String orderBy) {
        this.orderBy = orderBy; // 此处可优化 优化详情且看解析
        return this;
    }
}

BaseService 中我们看到了一个新的 PageParam ,参考了 PageInfo 用以包装/声明/分离分页参数和业务参数,且参数类型为泛型,即支持任何数据类型的业务参数 同时也可以看到 PageParam 实现了 IPage 接口,并且多了一个 orderBy 属性字段

import common.base.BaseService;
import dto.req.TemplateReqDto;
import dto.resp.TemplateRespDto;

public interface TemplateService extends BaseService<TemplateReqDtoTemplateeRespDto{
    // 同为interface接口, 业务Service只需要继承BaseService
    // 并根据实际使用场景声明请求参数和响应结果的Entity实体即可
}

在实际应用中,只需要声明我们通用的业务查询请求参数和响应结果即可

import dto.req.TemplateReqDto;
import dto.resp.TemplateRespDto;
import service.TemplateService;
import persistence.mapper.TemplateMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j // 基于lombok自动生成logger日志记录实例
@Service // SpringBoot中注册Service Bean的注解
@RequiredArgsConstructor






请到「今天看啥」查看全文


推荐文章
婚姻家庭那些事儿  ·  妈妈决定着家的温度
8 年前
摄像人网  ·  婚拍时这样的尴尬,真是够了!
8 年前
中国新闻周刊  ·  我们做了一件很性感的事
7 年前
百姓关注  ·  母亲老了,这些话请你不要说
7 年前