JDBC分页核心是将逻辑下沉至数据库执行,避免Java端遍历:一要按数据库类型编写适配SQL(如MySQL用LIMIT ? OFFSET ?,SQL Server/Oracle 12c+用OFFSET FETCH),二要用PreparedStatement安全传参并校验页码与页大小合法性,总数与分页数据需分两次查询,禁用ResultSet.absolute伪分页。

在 JDBC 中处理分页查询,核心是把分页逻辑下沉到数据库执行,而不是靠 Java 端遍历结果集。这样能减少网络传输、内存占用和数据库压力。关键在于两步:写对数据库适配的分页 SQL,再用 PreparedStatement 安全传参。
按数据库类型写分页 SQL
不同数据库语法差异大,不能一套 SQL 走天下:
-
MySQL / MariaDB:用
LIMIT ? OFFSET ?,参数顺序是「每页条数」、「跳过条数」
示例:SELECT * FROM user WHERE status = ? ORDER BY id DESC LIMIT ? OFFSET ?
传参时:`ps.setInt(1, 1); ps.setInt(2, 10); ps.setInt(3, (pageNum - 1) * pageSize);` -
SQL Server(2012+):用
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY
注意必须带ORDER BY,否则报错
示例:SELECT * FROM user WHERE status = ? ORDER BY id DESC OFFSET ? ROWS FETCH NEXT ? ROWS ONLY -
Oracle(12c+):用
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY(与 SQL Server 类似)
旧版本用ROWNUM嵌套子查询,可读性差、易出错,不推荐新项目使用
用 PreparedStatement 安全传参
避免拼接字符串导致 SQL 注入,也防止数字类型转换异常:
- 页码和页大小必须校验合法性(如
pageNum > 0、pageSize > 0 && pageSize ) - 计算偏移量时用
(pageNum - 1) * pageSize,别漏减 1 - 所有参数统一用
setInt()或setLong(),不要用字符串拼 offset 值
查总数和分页数据要分开执行
前端通常需要总记录数来算总页数,但多数数据库不支持单条 SQL 同时返回分页结果 + 总数(除非用窗口函数)。稳妥做法是:
立即学习“Java免费学习笔记(深入)”;
- 先执行一条
SELECT COUNT(*) FROM ... WHERE ...获取总数(条件需与分页查询完全一致) - 再执行带分页的主查询
- 把总数、当前页、页大小、结果列表一起封装进 Page 对象返回
不建议用 ResultSet#absolute 跳行
虽然 JDBC 提供 rs.absolute((pageNum - 1) * pageSize + 1) 配合 setMaxRows() 实现“伪分页”,但它本质是查全表再跳行,大数据量下性能极差,且部分驱动不支持。生产环境应禁用。


















