首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JSP 分頁功能失效:SQL 未實現分頁導致首頁顯示全部數據

     編輯:程式設計綜合問答

問題現象

分頁組件(頁碼、上/下頁)顯示正常,總頁數計算正確,**但所有數據集中顯示在第一頁**,翻頁無新數據。

根因定位

`execute()` 方法中 **SQL 查詢未加分頁限制**,一次性 `SELECT * FROM My_users` 取出全量數據裝入 `userList`,前端雖然分頁渲染,但數據源已是全量。

錯誤代碼片段


// 錯誤:無 LIMIT/OFFSET,全量查詢
sqlStr = "select * from My_users ";
// ... 拼接 where 但無分頁條件
rs = stmt.executeQuery(sqlStr);
while (rs.next()) { userList.add(user); } // 全量裝入

修復方案:數據庫層分頁 (MySQL 為例)


// 1. 計算偏移量 (page 從 1 開始)
int offset = (page - 1) * pageSize;

// 2. 統計總記錄數 (用於計算總頁數)
String countSql = "SELECT COUNT(*) FROM My_users";
try (ResultSet rsCnt = stmt.executeQuery(countSql)) {
    if (rsCnt.next()) recordCount = rsCnt.getLong(1);
}
pageCount = (recordCount + pageSize - 1) / pageSize;

// 3. 分頁查詢 (MySQL LIMIT offset, size)
String dataSql = "SELECT * FROM My_users ORDER BY Id DESC LIMIT ?, ?";
try (PreparedStatement ps = conn.prepareStatement(dataSql)) {
    ps.setInt(1, offset);
    ps.setInt(2, pageSize);
    try (ResultSet rs = ps.executeQuery()) {
        userList.clear(); // 關鍵:清空舊數據
        while (rs.next()) {
            // 映射對象...
            userList.add(user);
        }
    }
}

關鍵修正點

  1. SQL 必須包含 `LIMIT ?, ?`** (MySQL) / `OFFSET ? ROWS FETCH NEXT ? ROWS ONLY` (SQL Server 2012+/Oracle 12c+/PostgreSQL)。
  2. 使用 `PreparedStatement` 防注入**,參數化 `offset` 和 `pageSize`。
  3. 查詢前 `userList.clear()`**,避免多次查詢數據疊加。
  4. 總記錄數單獨查詢 `COUNT(*)`**,不可用 `ResultSet.last()`/`getRow()` (性能差、游標依賴)。

完善的分頁工具類 (通用)


public class PageResult {
    private List data;
    private long total;
    private int page;
    private int pageSize;
    // getter/setter...
}

public PageResult queryPage(Connection conn, int page, int pageSize) throws SQLException {
    PageResult result = new PageResult<>();
    result.setPage(page);
    result.setPageSize(pageSize);
    
    // 1. 總數
    try (PreparedStatement ps = conn.prepareStatement("SELECT COUNT(*) FROM My_users")) {
        try (ResultSet rs = ps.executeQuery()) {
            if (rs.next()) result.setTotal(rs.getLong(1));
        }
    }
    
    // 2. 分頁數據
    int offset = (page - 1) * pageSize;
    String sql = "SELECT * FROM My_users ORDER BY Id DESC LIMIT ?, ?";
    try (PreparedStatement ps = conn.prepareStatement(sql)) {
        ps.setInt(1, offset);
        ps.setInt(2, pageSize);
        try (ResultSet rs = ps.executeQuery()) {
            List list = new ArrayList<>();
            while (rs.next()) {
                User u = new User();
                u.setId(rs.getLong("Id"));
                // ... 其他字段映射
                list.add(u);
            }
            result.setData(list);
        }
    }
    return result;
}

前端 JSP 配合 JSTL 渲染



    
        ${user.id}
        ${user.userName}
        
    




    上一頁


    ${p}


    下一頁

避坑指南

錯誤模式後果修正
Java 內存分頁 (全量查出再 subList)OOM 風險、查詢慢、無法應對大數據量數據庫層 LIMIT/OFFSET
拼接 SQL 字符串 `LIMIT ${offset}, ${size}`SQL 注入風險PreparedStatement 參數化
不清空 List 重複添加翻頁數據疊加查詢前 `list.clear()`
用 `SELECT COUNT(*) OVER()` 窗口函數MySQL 8.0+ 支持,但較複雜簡單場景獨立 COUNT(*) 更清晰

總結

**分頁核心在 SQL**,而非 Java 邏輯或前端渲染。`LIMIT offset, size` (MySQL) 等分頁子句是標準解法。**「總數單獨查、數據分頁查、參數化防注入、List 查詢前清空」** 四步走,徹底解決「首頁全量、翻頁無數據」問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved