SpringBoot之JPA分页,结合Pageable和Swagger2

JPA分页

​当请求的数据总量很大时,这时候前端往往都会要求后端将数据分页返回。本文介绍SpringBoot下后端数据层使用JPA+MySQL时,如何分页返回数据(除了当前页面的数据,往往还要返回总页数这项数据)。

一、从头到尾自己实现分页:

Controller层:使用@RequestParam绑定page和pageSize参数,调用Service

Service层:

  1. 接收page、pageSize参数,调用Dao获得当前页数据;
  2. 调用Dao获得总数据量,再除以pageSize,获得总页数;
  3. 将当前页数据和总页数包装成VO返回给Controller

DAO层:

  1. 自己写SQL,使用limit语句获取当前页数据;
  2. 使用 select count(1)获得数据总量

可以看到,自己实现分页还是比较麻烦的,不详细写具体代码了,重点介绍下一种方法:

二、使用JPA自带的Pageable和Page:

Controller层:使用Pageable接收参数

    @GetMapping("/byEnterprise")
    public Response<PageVO<QuestionBankVO>> getQuestionBanksByEnterpriseId(@PageableDefault(page = 0, value = 6, sort = {"createdTime"}, direction = Sort.Direction.DESC) Pageable pageable) {
        return ResponseFactory.okResponse(questionBankService.getQuestionBanksByEnterpriseId(pageable, 1));
    }
  • Pageable不仅仅支持分页,还支持排序(单字段/多字段均支持)
  • @PageableDefault注解可以为pageable对象设置默认参数,即pageable参数非必须传入,可以利用该注解设置默认值。其中page是页数(从0开始),value是每页数据数量(即pageSize),sort是被排序的字段,direction是升序/降序
  • 访问该RESTful接口时,使用例子:http://localhost:8882/api/v1/questionBanks/byEnterprise?sort=id%2Cdesc&page=0&size=2 (传direction是在字段后加[,asc/desc],eg:id,desc,代表按id降序排列。也可以只写id不写direction,只写sort字段不写direction时,direction默认为asc)

Service层:利用DAO层获得的Page对象,可以获得当前页数据、总页数等信息

    @Override
    public PageVO<QuestionBankVO> getQuestionBanksByEnterpriseId(Pageable pageable, int enterpriseId) {
        Page<QuestionBank> result = questionBankDao.findByEnterpriseIdAndDisabledFalse(pageable, enterpriseId);

        List<QuestionBankVO> bankVOs = result.stream().map(b -> (QuestionBankVO) Converter.map(b, QuestionBankVO.class)).collect(Collectors.toList());
        return new PageVO<>(pageable.getPageNumber(), result.getTotalPages(), bankVOs);
    }

DAO层:传入Pageable,返回Page<T>

public interface QuestionBankDao extends JpaRepository<QuestionBank, Integer> {
    Page<QuestionBank> findByEnterpriseIdAndDisabledFalse(Pageable pageable, int enterpriseId);
}

自定义PageVO:

package com.yuantu.education.vo;

import lombok.Data;

import java.util.List;

/**
 * @author deng
 * @date 2018/12/13
 */
@Data
public class PageVO<T> {
    private int currentPage;
    private int totalPage;
    private List<T> data;

    public PageVO(){
        super();
    }

    public PageVO(int currentPage, int totalPage, List<T> data) {
        this.currentPage = currentPage;
        this.totalPage = totalPage;
        this.data = data;
    }
}

如果使用Swagger2.8.0,此时Swagger不会自动显示出Pageable参数。

想要让Swagger2能够针对Pageable参数显示接口参数,增加如下配置即可:

package com.yuantu.education.config;

import com.fasterxml.classmate.TypeResolver;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.domain.Pageable;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;

import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;

@Configuration
@SuppressWarnings("SpringJavaAutowiringInspection")
public class PageableParamConfig {
    @Bean
    public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
        return new AlternateTypeRuleConvention() {
            @Override
            public int getOrder() {
                return Ordered.LOWEST_PRECEDENCE;
            }

            @Override
            public List<AlternateTypeRule> rules() {
                return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
            }
        };
    }

    @ApiModel
    @Data
    static class Page {
        @ApiModelProperty("第page页,从0开始计数")
        private Integer page;

        @ApiModelProperty("每页数据数量")
        private Integer size;

        @ApiModelProperty("按属性排序,格式:属性(,asc|desc)")
        private List<String> sort;
    }
}

配置后Swagger2显示效果如图:
在这里插入图片描述

Ps: Swagger2的配置学习自:http://blog.51cto.com/7308310/2082742


后话:方法二对JPA框架的依赖性很强(从Controller到Service到DAO都依赖JPA框架);而方法一仅仅在DAO层依赖JPA。比如以后如果因为需求变更而想将框架从JPA迁移至MyBatis的话,方法一只需要修改DAO层代码,而方法二则从头到尾全要改。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
使用Spring Boot和JPA实现分页查询非常简单。首先,您需要创建一个带有`Pageable`参数的方法,该参数用于指定分页参数。然后,您可以在该方法中使用`Page`对象来返回分页结果。 在您提供的引用中,`StudentService`接口定义了一个名为`listStudents`的方法,该方法接受一个`Pageable`对象作为参数,并返回`Page<Student>`类型的结果。因此,您可以在该方法中实现分页查询逻辑。 为了使用分页功能,您还需要在您的项目中添加相关的依赖。在引用中,您可以看到添加了`spring-boot-starter-data-jpa`依赖,它提供了与JPA相关的功能,包括分页查询。除此之外,还需要添加其他必要的依赖,如`spring-boot-starter-web`和`mysql-connector-java`等。 综上所述,要在Spring Boot中使用JPA进行分页查询,您需要按照以下步骤操作: 1. 创建一个Spring Boot项目。 2. 在pom文件中添加必要的依赖,包括`spring-boot-starter-data-jpa`、`spring-boot-starter-web`、`mysql-connector-java`等。 3. 创建一个`Student`实体类,用于映射数据库表。 4. 创建一个`StudentService`接口,定义一个名为`listStudents`的方法,该方法接受一个`Pageable`对象作为参数,并返回`Page<Student>`类型的结果。 5. 在`StudentService`接口的实现类中,使用JPA的`findAll`方法来查询所有学生,并将结果进行分页处理,然后返回`Page<Student>`类型的结果。 6. 在您的控制器类中,注入`StudentService`并调用`listStudents`方法,将分页结果返回给前端。 通过以上步骤,您就可以在Spring Boot项目中使用JPA进行分页查询了。这样,您就可以方便地对大量数据进行分页展示和处理了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值