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

相关推荐
阿蒙Amon2 小时前
C#每日面试题-Task和ValueTask区别
java·开发语言·c#
Java程序员威哥2 小时前
【包教包会】SpringBoot依赖Jar指定位置打包:配置+原理+避坑全解析
java·开发语言·spring boot·后端·python·微服务·jar
a程序小傲2 小时前
中国邮政Java面试被问:边缘计算的数据同步和计算卸载
java·服务器·开发语言·算法·面试·职场和发展·边缘计算
Java程序员威哥2 小时前
Java微服务可观测性实战:Prometheus+Grafana+SkyWalking全链路监控落地
java·开发语言·python·docker·微服务·grafana·prometheus
毕设源码-邱学长2 小时前
【开题答辩全过程】以 面向警务应用的问答系统的设计与实现为例,包含答辩的问题和答案
java
Java后端的Ai之路2 小时前
【AI应用开发工程师】-分享Java 转 AI正确思路
java·开发语言·人工智能·java转行·程序员转型
孙张翼翔2 小时前
锁.................
java·开发语言
移幻漂流2 小时前
C/C++内存掌控之道:从内存泄漏到零开销抽象的进阶之路
java·c语言·c++
Java程序员威哥2 小时前
Spring AI快速上手:Java集成ChatGPT/文心一言,30分钟实现智能问答接口
java·人工智能·spring boot·后端·python·spring·云原生