分頁組件(頁碼、上/下頁)顯示正常,總頁數計算正確,**但所有數據集中顯示在第一頁**,翻頁無新數據。
`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); } // 全量裝入
// 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);
}
}
}
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;
}
${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 查詢前清空」** 四步走,徹底解決「首頁全量、翻頁無數據」問題。