Spring Data JPA 中的分页实现:从 BasePage 到 Pageable

news2025/5/10 17:42:10

文章目录

  • Spring Data JPA 中的分页实现:从 BasePage 到 Pageable
    • 背景:为什么需要分页?
    • 认识 BasePage 类
    • 深入 toPageable() 方法
      • 1. 处理页码和页面大小
      • 2. 处理排序方向
      • 3. 处理排序字段
      • 4. 生成 Pageable 对象
    • 实战:如何使用 BasePage
      • 1. 前端请求
      • 2. 后端控制器
      • 3. 查询数据库
      • 4. 返回结果
    • 小结


Spring Data JPA 中的分页实现:从 BasePage 到 Pageable

在现代 Web 开发中,分页是一个常见的需求。无论是展示商品列表、文章列表还是用户数据,当数据量较大时,分页不仅能提升用户体验,还能减轻服务器的压力。如果你使用的是 Spring Boot 和 Spring Data JPA,那么分页功能已经内置其中,开发者只需简单配置即可实现。今天,我们通过一个简单的 BasePage 类,来看看如何优雅地实现分页和排序功能。

背景:为什么需要分页?

假设你正在开发一个电商平台,数据库中有成千上万的商品记录。如果一次性将所有数据返回给前端,不仅加载速度会变慢,用户也很难从中找到所需信息。这时,分页就派上用场了:每页显示固定数量的记录(比如 10 条),用户可以通过翻页操作逐步浏览。

Spring Data JPA 提供了一个强大的接口 Pageable,它封装了分页和排序的逻辑。通过 Pageable,我们可以轻松实现“第几页”、“每页几条”以及“按什么字段排序”的功能。而今天的主角——BasePage 类,就是一个自定义的分页模型,通过它我们可以将前端传入的分页参数转换为 Pageable 对象。

认识 BasePage 类

BasePage 是一个简单的分页模型类,包含了分页和排序的核心属性。以下是它的代码结构:

public class BasePage {
    @ApiModelProperty("页码")
    Integer page;

    @ApiModelProperty("页大小")
    Integer size;

    @ApiModelProperty(value = "排序规则(ASC/DESC)", allowableValues = "ASC,DESC")
    String direction;

    @ApiModelProperty("排序字段")
    String[] properties;

    // 构造函数、getter 和 setter 略

    public Pageable toPageable() {
        page = page != null ? page : 0;
        size = size != null ? size : 9999;
        Sort.Direction dir = Sort.Direction.fromOptionalString(this.direction).orElse(Sort.Direction.DESC);
        Sort sort = (properties != null && properties.length > 0) ? 
                    Sort.by(dir, properties) : Sort.by(dir, "createdDate");
        return PageRequest.of(page, size, sort);
    }
}

这个类包含了四个关键属性:

  • page:页码,表示当前是第几页。
  • size:每页的大小,表示每页显示多少条记录。
  • direction:排序方向,可以是 "ASC"(升序)或 "DESC"(降序)。
  • properties:排序字段,表示按哪些字段排序。

toPageable() 方法则是这个类的核心,它将这些属性转化为 Spring Data JPA 所需的 Pageable 对象。

深入 toPageable() 方法

让我们一步步拆解 toPageable() 方法,看看它是如何工作的:

1. 处理页码和页面大小

page = page != null ? page : 0;
size = size != null ? size : 9999;
  • 如果 page 未设置(null),默认值为 0,表示第一页(Spring Data 的页码从 0 开始)。
  • 如果 size 未设置,默认值为 9999。这是一个很大的数字,通常是为了在未指定页面大小时尽量返回所有数据。不过在实际应用中,建议根据业务需求设置一个合理的默认值,比如 10 或 20。

2. 处理排序方向

Sort.Direction dir = Sort.Direction.fromOptionalString(this.direction).orElse(Sort.Direction.DESC);
  • Sort.Direction 是 Spring Data 的枚举类,表示排序方向。
  • fromOptionalString(this.direction) 尝试将 direction(如 “ASC” 或 “DESC”)解析为 Sort.Direction 类型。
  • 如果解析失败或 directionnull,则使用默认值 Sort.Direction.DESC(降序)。

3. 处理排序字段

Sort sort = (properties != null && properties.length > 0) ? 
            Sort.by(dir, properties) : Sort.by(dir, "createdDate");
  • 如果 properties 不为空,则按指定的字段排序。
  • 如果 properties 为空或未设置,则默认按 "createdDate"(创建时间)字段排序。
  • Sort.by(dir, properties) 创建了一个 Sort 对象,封装了排序方向和字段。

4. 生成 Pageable 对象

return PageRequest.of(page, size, sort);
  • 使用 PageRequest.of() 方法,将页码、页面大小和排序规则组合成一个 Pageable 对象。
  • 这个对象可以直接传递给 Spring Data 的查询方法。

实战:如何使用 BasePage

假设我们有一个商品管理的接口,需要支持分页和排序。以下是实现步骤:

1. 前端请求

前端发送一个 HTTP 请求,例如:

GET /products?page=1&size=10&direction=ASC&properties=price
  • page=1:请求第 2 页(从 0 开始计数)。
  • size=10:每页 10 条记录。
  • direction=ASC:按升序排序。
  • properties=price:按价格排序。

2. 后端控制器

在 Spring Boot 的控制器中接收参数并构造 BasePage

@RestController
@RequestMapping("/products")
public class ProductController {
    @Autowired
    private ProductRepository productRepository;

    @GetMapping
    public Page<Product> getProducts(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @RequestParam(required = false) String direction,
            @RequestParam(required = false) String[] properties) {
        
        BasePage basePage = new BasePage();
        basePage.setPage(page);
        basePage.setSize(size);
        basePage.setDirection(direction);
        basePage.setProperties(properties);

        Pageable pageable = basePage.toPageable();
        return productRepository.findAll(pageable);
    }
}

3. 查询数据库

ProductRepository 是一个 Spring Data JPA 提供的接口:

public interface ProductRepository extends JpaRepository<Product, Long> {
}

调用 findAll(Pageable pageable) 方法后,Spring Data 会自动生成 SQL 查询,返回分页后的结果。

4. 返回结果

最终返回的 JSON 可能长这样:

{
  "content": [
    {"id": 1, "name": "商品A", "price": 10.0},
    {"id": 2, "name": "商品B", "price": 15.0},
    ...
  ],
  "totalElements": 50,
  "totalPages": 5,
  "number": 1,
  "size": 10
}

小结

通过 BasePagetoPageable() 方法,我们实现了一个简单而灵活的分页模型。它的优点在于:

  • 简单易用:只需设置几个属性,就能生成 Pageable 对象。
  • 默认值友好:未设置的参数有合理的默认值,避免空指针问题。
  • 支持排序:灵活指定排序字段和方向,满足复杂需求。

当然,实际开发中还可以根据需求扩展 BasePage,比如添加参数验证、支持多字段排序等。Spring Data JPA 的分页功能非常强大,配合自定义模型类,可以让代码更优雅、更易维护。

如果你也正在为分页功能苦恼,不妨试试这种方式吧!有什么问题或想法,欢迎在评论区交流。


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2307785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能家居遥控革命!昂瑞微HS6621EM:用「芯」定义AIoT时代的语音交互标杆

AIoT爆发期&#xff0c;遥控器为何成为智能家居的「隐形战场」&#xff1f; 随着Meta、苹果等巨头加速布局空间计算&#xff0c;智能家居生态正从「单一设备联网」向「全场景无感交互」跃迁。作为高频使用的入口设备&#xff0c;语音遥控器的性能直接决定用户体验天花板。昂瑞微…

Grafana使用日志7--开启Sigv4

背景 在Grafana中&#xff0c;有些data source是需要开启sigv4认证的&#xff0c;例如OpenSearch&#xff0c;这个配置项默认是关闭的&#xff0c;这里我们介绍一下怎么开启 步骤 传统方式 如果我们想在Grafana中开启sigv4认证&#xff0c;我们需要在grafana.ini中修改一个…

【Redis】Redis 入门

借鉴枫枫知道 一、连接 redis 1.1 命令行连接 // 完整的命令 redis-cli -h 127.0.0.1 -p 6379 -a password// 简写 redis-cli// 认证&#xff0c;进行redis之后 auth password1.2 go 代码连接 package mainimport ("fmt""github.com/go-redis/redis" …

一文了解:部署 Deepseek 各版本的硬件要求

很多朋友在咨询关于 DeepSeek 模型部署所需硬件资源的需求&#xff0c;最近自己实践了一部分&#xff0c;部分信息是通过各渠道收集整理&#xff0c;so 仅供参考。 言归正转&#xff0c;大家都知道&#xff0c;DeepSeek 模型的性能在很大程度上取决于它运行的硬件。我们先看一下…

Mercury、LLaDA 扩散大语言模型

LLaDA 参考&#xff1a; https://github.com/ML-GSAI/LLaDA https://ml-gsai.github.io/LLaDA-demo/ 在线demo&#xff1a; https://huggingface.co/spaces/multimodalart/LLaDA Mercury 在线demo&#xff1a; https://chat.inceptionlabs.ai/ 速度很快生成

Windows环境下SuperMapGIS 11i 使用达梦数据库

1. 环境介绍&#xff1a; 1.1. 操作系统&#xff1a; windows server 2019 1.2. GIS 软件&#xff1a; 1.2.1. GIS 桌面 supermap-idesktopx-11.3.0-windows-x64-bin 下载链接&#xff1a;SuperMap技术资源中心|为您提供全面的在线技术服务 安装教程&#xff1a;绿色版&…

Claude 3.7 Sonnet深度解析:混合推理模型如何重塑AI编程能力

引言 2025年2月25日&#xff0c;人工智能领域领先企业Anthropic正式发布了新一代大语言模型Claude 3.7 Sonnet。作为全球首个混合推理AI模型&#xff0c;Claude 3.7 Sonnet在编程开发、逻辑推理以及任务处理效率等方面实现了突破性进展。本文将从核心特性、性能评测、竞品对比…

IP属地是通过卫星定位的吗?如何保护用户隐私

在数字时代&#xff0c;网络空间成为了人们日常生活不可或缺的一部分。随着社交媒体、在线服务等平台的兴起&#xff0c;用户IP属地信息的重要性日益凸显。然而&#xff0c;关于IP属地是如何确定的&#xff0c;尤其是是否通过卫星定位这一问题&#xff0c;却常常引发公众的疑问…

一键部署DeepSeek

腾讯Cloud Studio提供DeepSeek一键部署功能&#xff0c;0行代码&#xff0c;秒级部署使用&#xff01; 重点是每月免费提供10000分钟&#xff01; 不用等待模型下载&#xff0c;创建即可使用。 内置 Ollama、DeepSeek-R1 1.5B、7B、8B、14B 及 32B 模型。 热门模板 AI模板 前…

自动化测试无法启动(java.net.SocketException)

在运行测试代码,对浏览器进行自动化操作时,遇到了以下问题,添加依赖,编写了测试代码,但是程序无法运行 这个有两种原因(我使用的是谷歌浏览器): 网络问题: 因为需要从GitHub上下载对应包,所以有时候可能会出现网络问题,这个时候可以打开VPN之后,重新对程序进行启动 浏览器版本…

WPF中对滚动条进行平滑滚动

有时候我们在动态添加内容时&#xff0c;需要将滚动条滚动到指定内容处。 一般我们会调用ScrollViewer的ScrollToVerticalOffset&#xff08;垂直方向&#xff09;函数和ScrollToHorizontalOffset&#xff08;水平方向&#xff09;函数来控制滚动条滚动到指定位置。 正常滚动效…

Threejs 解析几何体提取顶点数据流程

目录 前言 原生WebGL 整体解析过程简介 顶点颜色属性Geometry.colors Geometry转化为BufferGeometry 相关函数 WebGLAttributes.js WebGLGeometries.js WebGLObjects.js WebGLRenderer.js WebGLRenderer.js 前言 解析几何体对象&#xff0c;提取顶点数据&#xf…

YOLOv5 + SE注意力机制:提升目标检测性能的实践

一、引言 目标检测是计算机视觉领域的一个重要任务&#xff0c;广泛应用于自动驾驶、安防监控、工业检测等领域。YOLOv5作为YOLO系列的最新版本&#xff0c;以其高效性和准确性在实际应用中表现出色。然而&#xff0c;随着应用场景的复杂化&#xff0c;传统的卷积神经网络在处…

极简Redis速成学习

redis是什么&#xff1f; 是一种以键值对形式存储的数据库&#xff0c;特点是基于内存存储&#xff0c;读写快&#xff0c;性能高&#xff0c;常用于缓存、消息队列等应用情境 redis的五种数据类型是什么&#xff1f; 分别是String、Hash、List、Set和Zset&#xff08;操作命…

教育培训APP开发全攻略:从网校系统源码搭建到功能优化的技术方案

本篇文章&#xff0c;笔者将从网校系统源码搭建到功能优化的角度&#xff0c;全面解析教育培训APP的开发技术方案&#xff0c;帮助企业和开发者更好地理解如何提升在线教育平台的性能与用户体验。 一、教育培训APP开发的核心架构 教育培训APP的架构设计是其能否顺利运行和扩展…

网络安全与认知安全的区别 网络和安全的关系

前言 说说信息安全 与网络安全 的关系 一、包含和被包含的关系 信息安全包括网络安全&#xff0c;信息安全还包括操作系统安全&#xff0c;数据库安全 &#xff0c;硬件设备和设施安全&#xff0c;物理安全&#xff0c;人员安全&#xff0c;软件开发&#xff0c;应用安全等。…

智能机器人加速进化:AI大模型与传感器的双重buff加成

Deepseek不仅可以在手机里为你解答现在的困惑、占卜未来的可能&#xff0c;也将成为你的贴心生活帮手&#xff01; 2月21日&#xff0c;追觅科技旗下Dreamehome APP正式接入DeepSeek-R1大模型&#xff0c;2月24日发布的追觅S50系列扫地机器人也成为市面上首批搭载DeepSeek-R1的…

Java从根上理解 ConcurrentHashMap:缓存机制与性能优化

目录 一、ConcurrentHashMap 的核心原理1. 数据结构2. 锁机制3. 扩容机制二、ConcurrentHashMap 的缓存机制1. 缓存的实现2. 缓存的更新策略三、ConcurrentHashMap 的性能优化1. 减少锁竞争2. 优化数据结构3. 合理设置容量和负载因子四、具体代码示例1. 创建 ConcurrentHashMap…

通过百度构建一个智能体

通过百度构建一个智能体 直接可用,我不吝啬算力 首先部署一个模型,我们选用deepseek14 构建智能体思考步骤,甚至多智能体; from openai import OpenAIclass Agent:def __init__(self, api_key, base_url, model

【MySQL】(1) 数据库基础

一、什么是数据库 数据库自行选择了合适的数据结构来组织数据&#xff0c;方便用户写入&#xff08;存储介质&#xff0c;如硬盘&#xff0c;机器断电不会丢失数据&#xff09;和查询数据。在数据结构部分&#xff0c;我们讲到的 ArrayList、HashMap 集合类对象也能存储数据&am…