JPA实现分页查询

一、搭建JPA项目

参考博客地址https://blog.csdn.net/only_foryou/article/details/155886258?spm=1001.2014.3001.5501

只需要增加一个分页入参即可

java 复制代码
Pageable pageable = PageRequest.of(page, size);
复制代码
Repository方法增加 分页对象 Pageable pageable

如:

java 复制代码
    Page<Student> findByName(String name, Pageable pageable);

二、entity

java 复制代码
package com.qiu.entity;

import jakarta.persistence.*;
import lombok.Data;

import java.time.LocalDateTime;

/**
 * 描述:学生实体类
 *
 * @author: qxd
 * @date: 2025/12/11 22:09
 * @version: 1.0.0
 */
@Entity
@Table(name = "student")
@Data
public class Student {
    /**
     * 学生ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    /**
     * 学生姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 性别
     */
    private String gender;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 电话
     */
    private String phone;

    /**
     * 地址
     */
    private String address;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;

    /**
     * 添加版本控制字段
     */
    @Version
    private Long version;
}

**三、**Repository

java 复制代码
package com.qiu.repository;

import com.qiu.entity.Student;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 描述:学生数据访问接口
 *
 * @author: qxd
 * @date: 2025/12/12 22:11
 * @version: 1.0.0
 */
public interface StudentRepository extends JpaRepository<Student, Integer> {

    /**
     * 根据姓名查询学生列表
     * @param name 学生姓名
     * @return 学生列表
     */
    List<Student> findByName(String name);

    /**
     * 根据邮箱查询学生
     * @param email 学生邮箱
     * @return 学生对象
     */
    Student findByEmail(String email);

    /**
     * 根据性别查询学生列表
     * @param gender 学生性别
     * @return 学生列表
     */
    List<Student> findByGender(String gender);

    /**
     * 根据年龄范围查询学生
     * @param minAge 最小年龄
     * @param maxAge 最大年龄
     * @return 学生列表
     */
    List<Student> findByAgeBetween(int minAge, int maxAge);

    /**
     * 根据姓名模糊查询
     * @param name 姓名关键字
     * @return 学生列表
     */
    List<Student> findByNameContaining(String name);

    /**
     * 自定义JPQL查询 - 根据邮箱更新学生地址
     * @param address 新地址
     * @param email 学生邮箱
     * @return 影响行数
     */
    @Modifying
    @Transactional
    @Query("UPDATE Student s SET s.address = ?1 WHERE s.email = ?2")
    int updateAddressByEmail(String address, String email);

    /**
     * 自定义JPQL查询 - 根据性别删除学生
     * @param gender 性别
     * @return 删除记录数
     */
    @Modifying
    @Transactional
    @Query("DELETE FROM Student s WHERE s.gender = ?1")
    int deleteByGender(String gender);


    /**
     * 分页查询 - 根据姓名查询学生列表
     * @param name 学生姓名
     * @param pageable 分页参数
     * @return 学生列表
     */
    Page<Student> findByName(String name, Pageable pageable);

    /**
     * 分页查询 - 根据性别查询学生列表
     * @param gender 学生性别
     * @param pageable 分页参数
     * @return 学生列表
     */
    Page<Student> findByGender(String gender, Pageable pageable);

    /**
     * 分页查询 - 根据姓名模糊查询
     * @param name 姓名关键字
     * @param pageable 分页参数
     * @return 学生列表
     */
    Page<Student> findByNameContaining(String name, Pageable pageable);

    @Query("SELECT s FROM Student s WHERE s.gender = :gender")
    Page<Student> findByGenderWithPagination(@Param("gender") String gender, Pageable pageable);

    @Query("SELECT s FROM Student s WHERE s.name LIKE %:name%")
    Page<Student> findByNameContainingWithPagination(@Param("name") String name, Pageable pageable);

}

**四、**Service

java 复制代码
package com.qiu.service;


import com.qiu.entity.Student;
import org.springframework.data.domain.Page;

import java.util.List;
import java.util.Optional;

/**
 * 描述:学生服务接口
 *
 * @author: qxd
 * @date: 2025/12/11 21:36
 * @version: 1.0.0
 */
public interface StudentService {

    /**
     * 查询所有学生
     * @return 学生列表
     */
    List<Student> findAll();

    /**
     * 根据ID查询学生
     * @param id 学生ID
     * @return 学生对象
     */
    Optional<Student> findById(Integer id);

    /**
     * 根据姓名查询学生列表
     * @param name 学生姓名
     * @return 学生列表
     */
    List<Student> findByName(String name);

    /**
     * 根据邮箱查询学生
     * @param email 学生邮箱
     * @return 学生对象
     */
    Student findByEmail(String email);

    /**
     * 根据性别查询学生列表
     * @param gender 学生性别
     * @return 学生列表
     */
    List<Student> findByGender(String gender);

    /**
     * 根据年龄范围查询学生
     * @param minAge 最小年龄
     * @param maxAge 最大年龄
     * @return 学生列表
     */
    List<Student> findByAgeRange(int minAge, int maxAge);

    /**
     * 根据姓名模糊查询
     * @param name 姓名关键字
     * @return 学生列表
     */
    List<Student> findByNameContaining(String name);

    /**
     * 保存学生信息
     * @param student 学生对象
     * @return 保存后的学生对象
     */
    Student save(Student student);

    /**
     * 批量保存学生信息
     * @param students 学生列表
     * @return 保存后的学生列表
     */
    List<Student> saveAll(List<Student> students);

    /**
     * 根据邮箱更新学生地址
     * @param address 新地址
     * @param email 学生邮箱
     * @return 影响行数
     */
    int updateAddressByEmail(String address, String email);

    /**
     * 根据性别删除学生
     * @param gender 性别
     * @return 删除记录数
     */
    int deleteByGender(String gender);

    /**
     * 根据ID删除学生
     * @param id 学生ID
     */
    void deleteById(Integer id);

    /**
     * 删除所有学生
     */
    void deleteAll();

    /**
     * 获取所有学生并分页
     * @param page 页码
     * @param size 每页大小
     * @return 学生列表
     */
    public Page<Student> getAllStudents(int page, int size);

    /**
     * 根据姓名分页查询学生
     * @param name 姓名关键字
     * @param page 页码
     * @param size 每页大小
     * @return 学生列表
     */
    public Page<Student> getStudentsByName(String name, int page, int size) ;

    /**
     * 根据排序规则分页查询学生
     * @param page 页码
     * @param size 每页大小
     * @param sortBy 排序字段
     * @param direction 排序方向
     * @return 学生列表
     */
    public Page<Student> getStudentsWithSort(int page, int size, String sortBy, String direction) ;
}

**五、**ServiceImpl

java 复制代码
package com.qiu.service.impl;

import com.qiu.entity.Student;
import com.qiu.repository.StudentRepository;
import com.qiu.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
 * 描述:学生服务实现类
 *
 * @author: qxd
 * @date: 2025/12/11 21:37
 * @version: 1.0.0
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Override
    public List<Student> findAll() {
        return studentRepository.findAll();
    }

    @Override
    public Optional<Student> findById(Integer id) {
        return studentRepository.findById(id);
    }

    @Override
    public List<Student> findByName(String name) {
        return studentRepository.findByName(name);
    }

    @Override
    public Student findByEmail(String email) {
        return studentRepository.findByEmail(email);
    }

    @Override
    public List<Student> findByGender(String gender) {
        return studentRepository.findByGender(gender);
    }

    @Override
    public List<Student> findByAgeRange(int minAge, int maxAge) {
        return studentRepository.findByAgeBetween(minAge, maxAge);
    }

    @Override
    public List<Student> findByNameContaining(String name) {
        return studentRepository.findByNameContaining(name);
    }

    @Override
    public Student save(Student student) {
        // 对于新创建的实体,确保 ID 为 null
        if (student.getId() != null && student.getId() <= 0) {
            student.setId(null);
        }
        return studentRepository.save(student);
    }

    @Override
    public List<Student> saveAll(List<Student> students) {
        return studentRepository.saveAll(students);
    }

    @Override
    public int updateAddressByEmail(String address, String email) {
        return studentRepository.updateAddressByEmail(address, email);
    }

    @Override
    public int deleteByGender(String gender) {
        return studentRepository.deleteByGender(gender);
    }

    @Override
    public void deleteById(Integer id) {
        studentRepository.deleteById(id);
    }

    @Override
    public void deleteAll() {
        studentRepository.deleteAll();
    }

    @Override
    public Page<Student> getAllStudents(int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return studentRepository.findAll(pageable);
    }
    @Override
    public Page<Student> getStudentsByName(String name, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return studentRepository.findByName(name, pageable);
    }

    @Override
    public Page<Student> getStudentsWithSort(int page, int size, String sortBy, String direction) {
        Sort sort = direction.equalsIgnoreCase("desc") ?
                Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
        Pageable pageable = PageRequest.of(page, size, sort);
        return studentRepository.findAll(pageable);
    }
}

六、Controller

java 复制代码
package com.qiu.controller;

import com.qiu.entity.Student;
import com.qiu.service.StudentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * 描述:学生控制器
 *
 * @author: qxd
 * @date: 2025/12/11 21:38
 * @version: 1.0.0
 */
@RestController
@RequestMapping("/students")
@Tag(name = "学生管理", description = "学生信息的增删改查操作")
public class StudentController {

    @Autowired
    private StudentService studentService;

    /**
     * 查询所有学生
     * @return 学生列表
     */
    @GetMapping
    @Operation(summary = "查询所有学生", description = "获取系统中所有的学生信息")
    @ApiResponse(responseCode = "200", description = "成功获取学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public ResponseEntity<List<Student>> getAllStudents() {
        List<Student> students = studentService.findAll();
        return ResponseEntity.ok(students);
    }

    /**
     * 根据ID查询学生
     * @param id 学生ID
     * @return 学生对象
     */
    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询学生", description = "通过学生ID获取特定学生信息")
    @Parameter(name = "id", description = "学生ID", required = true)
    @ApiResponse(responseCode = "200", description = "成功获取学生信息",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    @ApiResponse(responseCode = "404", description = "学生不存在")
    public ResponseEntity<Student> getStudentById(@PathVariable Integer id) {
        Optional<Student> student = studentService.findById(id);
        return student.map(ResponseEntity::ok)
                     .orElse(ResponseEntity.notFound().build());
    }

    /**
     * 根据姓名查询学生列表
     * @param name 学生姓名
     * @return 学生列表
     */
    @GetMapping("/name/{name}")
    @Operation(summary = "根据姓名查询学生", description = "通过学生姓名获取匹配的学生列表")
    @Parameter(name = "name", description = "学生姓名", required = true)
    @ApiResponse(responseCode = "200", description = "成功获取学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public ResponseEntity<List<Student>> getStudentsByName(@PathVariable String name) {
        List<Student> students = studentService.findByName(name);
        return ResponseEntity.ok(students);
    }

    /**
     * 根据邮箱查询学生
     * @param email 学生邮箱
     * @return 学生对象
     */
    @GetMapping("/email/{email}")
    @Operation(summary = "根据邮箱查询学生", description = "通过学生邮箱获取特定学生信息")
    @Parameter(name = "email", description = "学生邮箱", required = true)
    @ApiResponse(responseCode = "200", description = "成功获取学生信息",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    @ApiResponse(responseCode = "404", description = "学生不存在")
    public ResponseEntity<Student> getStudentByEmail(@PathVariable String email) {
        Student student = studentService.findByEmail(email);
        return student != null ?
               ResponseEntity.ok(student) :
               ResponseEntity.notFound().build();
    }

    /**
     * 根据性别查询学生列表
     * @param gender 学生性别
     * @return 学生列表
     */
    @GetMapping("/gender/{gender}")
    @Operation(summary = "根据性别查询学生", description = "通过学生性别获取匹配的学生列表")
    @Parameter(name = "gender", description = "学生性别", required = true)
    @ApiResponse(responseCode = "200", description = "成功获取学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public ResponseEntity<List<Student>> getStudentsByGender(@PathVariable String gender) {
        List<Student> students = studentService.findByGender(gender);
        return ResponseEntity.ok(students);
    }

    /**
     * 根据年龄范围查询学生
     * @param minAge 最小年龄
     * @param maxAge 最大年龄
     * @return 学生列表
     */
    @GetMapping("/age")
    @Operation(summary = "根据年龄范围查询学生", description = "通过年龄范围获取匹配的学生列表")
    @Parameter(name = "minAge", description = "最小年龄", required = true)
    @Parameter(name = "maxAge", description = "最大年龄", required = true)
    @ApiResponse(responseCode = "200", description = "成功获取学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public ResponseEntity<List<Student>> getStudentsByAgeRange(
            @RequestParam int minAge,
            @RequestParam int maxAge) {
        List<Student> students = studentService.findByAgeRange(minAge, maxAge);
        return ResponseEntity.ok(students);
    }

    /**
     * 保存学生信息
     * @param student 学生对象
     * @return 保存后的学生对象
     */
    @PostMapping
    @Operation(summary = "创建学生", description = "新增学生信息")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            description = "学生信息",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)),
            required = true)
    @ApiResponse(responseCode = "200", description = "成功创建学生",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public ResponseEntity<Student> createStudent(@RequestBody Student student) {
        Student savedStudent = studentService.save(student);
        return ResponseEntity.ok(savedStudent);
    }

    /**
     * 批量保存学生信息
     * @param students 学生列表
     * @return 保存后的学生列表
     */
    @PostMapping("/batch")
    @Operation(summary = "批量创建学生", description = "批量新增学生信息")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            description = "学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)),
            required = true)
    @ApiResponse(responseCode = "200", description = "成功创建学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public ResponseEntity<List<Student>> createStudents(@RequestBody List<Student> students) {
        List<Student> savedStudents = studentService.saveAll(students);
        return ResponseEntity.ok(savedStudents);
    }

    /**
     * 根据邮箱更新学生地址
     * @param address 新地址
     * @param email 学生邮箱
     * @return 影响行数
     */
    @PutMapping("/address")
    @Operation(summary = "更新学生地址", description = "根据邮箱更新学生地址信息")
    @Parameter(name = "address", description = "新地址", required = true)
    @Parameter(name = "email", description = "学生邮箱", required = true)
    @ApiResponse(responseCode = "200", description = "成功更新地址")
    public ResponseEntity<Integer> updateStudentAddress(
            @RequestParam String address,
            @RequestParam String email) {
        int result = studentService.updateAddressByEmail(address, email);
        return ResponseEntity.ok(result);
    }

    /**
     * 根据ID删除学生
     * @param id 学生ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除学生", description = "根据ID删除学生信息")
    @Parameter(name = "id", description = "学生ID", required = true)
    @ApiResponse(responseCode = "204", description = "成功删除学生")
    public ResponseEntity<Void> deleteStudent(@PathVariable Integer id) {
        studentService.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    /**
     * 根据性别删除学生
     * @param gender 性别
     * @return 删除记录数
     */
    @DeleteMapping("/gender/{gender}")
    @Operation(summary = "根据性别删除学生", description = "根据性别批量删除学生信息")
    @Parameter(name = "gender", description = "学生性别", required = true)
    @ApiResponse(responseCode = "200", description = "成功删除学生")
    public ResponseEntity<Integer> deleteStudentsByGender(@PathVariable String gender) {
        int count = studentService.deleteByGender(gender);
        return ResponseEntity.ok(count);
    }
    /**
     * 分页搜索学生
     * @param name 学生姓名关键字
     * @param page 页码,默认为0
     * @param size 每页大小,默认为10
     * @return 分页的学生搜索结果
     */
    @GetMapping("/getStudentsByName")
    @Operation(summary = "分页搜索学生", description = "根据姓名关键字搜索学生信息的分页结果")
    @Parameter(name = "name", description = "学生姓名关键字", required = true)
    @Parameter(name = "page", description = "页码", required = false, example = "0")
    @Parameter(name = "size", description = "每页大小", required = false, example = "10")
    @ApiResponse(responseCode = "200", description = "成功获取分页搜索结果",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public Page<Student> getStudentsByName(
            @RequestParam String name,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {

        return studentService.getStudentsByName(name, page, size);
    }
    /**
     * 分页查询所有学生
     * @param page 页码,默认为0
     * @param size 每页大小,默认为10
     * @param sortBy 排序字段,默认为id
     * @param direction 排序方向,默认为asc
     * @return 分页的学生数据
     */
    @GetMapping("/getStudentsWithSort")
    @Operation(summary = "分页查询所有学生", description = "获取系统中所有学生信息的分页结果")
    @ApiResponse(responseCode = "200", description = "成功获取分页学生列表",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Student.class)))
    public Page<Student> getStudentsWithSort(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "id") String sortBy,
            @RequestParam(defaultValue = "asc") String direction) {

        return studentService.getStudentsWithSort(page, size, sortBy, direction);
    }

}

七、项目地址

https://gitee.com/qiuxiaodong/demo

项目名称:demo-springboot-jpa

相关推荐
程序员侠客行2 小时前
Mybatis连接池实现及池化模式
java·后端·架构·mybatis
时艰.2 小时前
Java 并发编程 — 并发容器 + CPU 缓存 + Disruptor
java·开发语言·缓存
Honmaple2 小时前
QMD (Quarto Markdown) 搭建与使用指南
后端
丶小鱼丶2 小时前
并发编程之【优雅地结束线程的执行】
java
市场部需要一个软件开发岗位2 小时前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
忆~遂愿2 小时前
GE 引擎进阶:依赖图的原子性管理与异构算子协作调度
java·开发语言·人工智能
MZ_ZXD0012 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
PP东2 小时前
Flowable学习(二)——Flowable概念学习
java·后端·学习·flowable
ManThink Technology2 小时前
如何使用EBHelper 简化EdgeBus的代码编写?
java·前端·网络
invicinble2 小时前
springboot的核心实现机制原理
java·spring boot·后端