You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

分页场景下如何对全量记录执行数据筛选(Spring Boot+Postgres+React)

实现全量筛选分页的方案

核心逻辑是将筛选参数和分页参数共同传给后端,后端先执行全量数据筛选,再对筛选后的结果集做分页计算,避免先分页后筛选导致只能过滤当前页数据的问题。

后端(Spring Boot + Postgres)实现

1. 统一参数接收

新增参数接收类,同时承载分页参数和筛选参数:

import lombok.Data;

@Data
public class MessageQueryReq {
    // 分页参数
    private Integer pageNumber = 1;
    private Integer pageSize = 10;
    // 筛选参数,可根据业务新增
    private String status;
    private String acknowledgeMsg;
}

2. 动态条件查询+分页

不管用JPA、MyBatis还是原生SQL,都要保证执行顺序:先执行where条件过滤全量数据,再做分页计算。以Spring Data JPA + Specification动态查询为例:

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.data.jpa.domain.Specification;
import jakarta.persistence.criteria.Predicate;
import cn.hutool.core.util.StrUtil;

public Page<MessageDTO> queryMessageList(MessageQueryReq req) {
    // 构造动态筛选条件
    Specification<Message> spec = (root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
        // 状态筛选不为空时添加条件
        if (StrUtil.isNotBlank(req.getStatus())) {
            predicates.add(cb.equal(root.get("status"), req.getStatus()));
        }
        // 回执内容模糊筛选
        if (StrUtil.isNotBlank(req.getAcknowledgeMsg())) {
            predicates.add(cb.like(root.get("acknowledgeMsg"), "%" + req.getAcknowledgeMsg() + "%"));
        }
        return cb.and(predicates.toArray(new Predicate[0]));
    };

    // 构造分页参数:JPA默认页码从0开始,和前端约定好偏移规则
    Pageable pageable = PageRequest.of(
        req.getPageNumber() - 1, 
        req.getPageSize(), 
        Sort.by(Sort.Direction.DESC, "msg_id")
    );

    // JPA会先执行count查询计算符合条件的总条数,再查询当前页数据
    Page<Message> messagePage = messageRepository.findAll(spec, pageable);
    
    // 转换为DTO,封装为你要求的返回格式即可,totalRecords取messagePage.getTotalElements(),numPages取messagePage.getTotalPages()
}

如果用原生Postgres SQL,写法参考:

-- 先查符合条件的总条数
SELECT count(*) FROM message WHERE status = ? AND acknowledge_msg LIKE ?;
-- 再查当前页数据
SELECT * FROM message WHERE status = ? AND acknowledge_msg LIKE ? ORDER BY msg_id DESC LIMIT ? OFFSET ?;

优化建议

对高频筛选的字段添加索引,降低全表扫描的性能损耗:

CREATE INDEX idx_message_status ON message(status);

前端(React)实现

1. 状态管理新增筛选变量

import { useState } from 'react';
import axios from 'axios';

const MessageList = () => {
    // 分页状态
    const [pageNumber, setPageNumber] = useState(1);
    const [pageSize, setPageSize] = useState(10);
    // 筛选状态
    const [filters, setFilters] = useState({
        status: '',
        acknowledgeMsg: ''
    });
    // 列表数据状态
    const [list, setList] = useState([]);
    const [total, setTotal] = useState(0);

2. 统一请求逻辑

不管是切换分页还是修改筛选条件,都要携带当前所有筛选参数请求接口,修改筛选条件时默认重置到第一页:

// 统一请求方法
    const fetchList = async (currentPage, currentSize, currentFilters) => {
        const res = await axios.get('/api/message/list', {
            params: {
                pageNumber: currentPage,
                pageSize: currentSize,
                ...currentFilters
            }
        });
        const { dtoList, totalRecords } = res.data.messages;
        setList(dtoList);
        setTotal(totalRecords);
    };

    // 筛选条件变更触发
    const handleFilterUpdate = (newFilters) => {
        setFilters(newFilters);
        // 重置到第一页
        setPageNumber(1);
        fetchList(1, pageSize, newFilters);
    };

    // 分页切换触发
    const handlePageChange = (newPage) => {
        setPageNumber(newPage);
        fetchList(newPage, pageSize, filters);
    };

这样每次请求的都是筛选后全量数据的对应分页,完全符合需求。

内容的提问来源于stack exchange,提问作者rudeTool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 16:45:04