分頁操作在開發中可以說是最基本的操作,特別是在做各種後臺管理系統的時候,不可能一次性查詢一千條、一萬條資料。
這時候就需要進行分頁操作。那麼在Java後端當中是如何實現分頁的呢?下面就來聊一聊Java後端分頁。
Java分頁原理
首先說說分頁的原理。有幾個名詞需要解釋一下,資料總數,每頁顯示的記錄數,當前頁,總頁數。
.1.假設某張表中總條數: total
.2.每頁顯示記錄數:pageSize
.3.當前頁:pageNum
.4.總頁數:pages
第一步:頁面當中需要傳入兩個資料,每頁顯示的記錄數和當前頁;
第二步:查詢某張表的總數賦值給total;
第三步:計算總頁數 總頁數 = Math.ceil(總條數 * 1.0 / 每頁顯示記錄數);
第四步:封裝結果返回資料。
說明:總條數 * 1.0表示把一個整數轉換為double型別的資料進行計算,否則兩個整數相除,計算結果就是一個整數會捨棄掉小數部分。
Math.ceil()表示向上取整。舉例每頁顯示6條資料,如果總共有8條資料,應該顯示為2頁,而不是1頁。
示例一:如果每頁顯示5條,總資料分別為15,16,19該顯示為多少條資料。
Math.ceil(15 * 0.1 / 5) 為3,Math.ceil(16 * 0.1 / 5) 為4,Math.ceil(19 * 0.1 / 5) 為4。符合要求,重點需要理解當最後一頁的資料不滿一頁時,也需要單獨顯示為一頁。
Mysql分頁原理
Mysql中分頁需要使用一個關鍵字limit,語法如下
Select * from 表 limit offset,size;
後面跟一個引數或者是兩個引數。只跟一個參數列示從第一條記錄開始,取size條記錄。
如果跟兩個引數,第一個引數offset表示偏移量,第二個引數size表示獲取的記錄數。
下面來做一個簡單的測試,建表語句如下,
DROP TABLE IF EXISTS page_test;
CREATE TABLE `page_test` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`name` varchar(16) DEFAULT NULL COMMENT '名稱',
`age` int(11) DEFAULT '0' COMMENT '年齡',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='分頁測試表';
測試資料如下,
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('1', '測試名稱1', '1');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('2', '測試名稱2', '2');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('3', '測試名稱3', '3');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('4', '測試名稱4', '4');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('5', '測試名稱5', '5');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('6', '測試名稱6', '6');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('7', '測試名稱7', '7');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('8', '測試名稱8', '8');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('9', '測試名稱9', '9');
INSERT INTO `manage`.`page_test` (`id`, `name`, `age`) VALUES ('10', '測試名稱10', '10');
下面進行查詢測試:
SELECT * FROM page_test order by id asc limit 0,3;
SELECT * FROM page_test order by id asc limit 3;
上面兩個查詢語句結果一致。
SELECT * FROM page_test order by id asc limit 1, 3;
SELECT * FROM page_test order by id asc limit 3,3;
SELECT * FROM page_test order by id asc limit 6,3;
從查詢的結果中可以看出,如果每頁顯示3條資料,limit 0,3表示查詢第一頁;limit 3,3表示查詢第二頁;limit 6, 3表示查詢第3頁。
因此可以推匯出一個公式:查詢起始位置 = (當前頁 - 1) * 每頁顯示記錄數。然後每次分頁查詢時,動態傳入limit後面的兩個引數即可。
Java程式碼實現示例
@Getter
@Setter
@NoArgsConstructor
public class PageReSult<T> {
// 資料總數
private Integer total;
// 當前頁碼
private Integer pageNum;
// 每頁顯示記錄數
private Integer pageSize;
// 總頁數
private Integer pages;
// 列表資料
private List<T> data;
}
說明: Set/get/建構函式使用的是Lombok實現。
分頁思路如下:
.a.獲取頁面中傳遞的引數;
.b.查詢總條數;
.c.計算mysql中的起始查詢位置,查詢當前頁的資料;
.d.獲取當前頁的資料;
.e.封裝查詢結果;
.f.返回資料;
具體示例程式碼如下
@WebServlet("/pageTest")
public class PageTestApi extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取分頁引數
String pageNumStr = req.getParameter("pageNum");
String pageSizeStr = req.getParameter("pageSize");
// 將分頁引數轉換為整數
Integer pageNum = Integer.parseInt(pageNumStr);
Integer pageSize = Integer.parseInt(pageSizeStr);
System.out.println("pageNum--->" + pageNum + ";pageSize=" + pageSize);
// 查詢總條數
String countSql = " SELECT count(*) total FROM page_test ";
PreparedStatement stmt = null;
Integer total = 0;
PageReSult pageReSult = new PageReSult();
// 使用工具類獲取資料庫連線
try (Connection conn = JDBCUtils.getConnection();){
// 獲取資料庫操作物件 prepareStatement 可以預編譯sql防止sql注入
stmt = conn.prepareStatement(countSql);
// 執行查詢
ResultSet rs = stmt.executeQuery();
// 獲取查詢結果
if(rs.next()){
total = rs.getInt("total");
}
System.out.println("total--->" + total);
// 計算 mysql 中 limit 查詢的起始位置
int start = (pageNum - 1) * pageSize;
// 查詢分頁資料,最好按照某個欄位進行排序,否則查詢結果可能會不準確
String selectSql = " SELECT * FROM page_test order by id asc limit ?,?";
stmt = conn.prepareStatement(selectSql);
stmt.setObject(1, start);
stmt.setObject(2, pageSize);
rs = stmt.executeQuery();
List<EntityTest> data = new ArrayList<>();
// 獲取查詢結果集
while (rs.next()){
EntityTest entityTest = new EntityTest();
entityTest.setId(rs.getLong("id"));
entityTest.setName(rs.getString("name"));
entityTest.setAge(rs.getInt("age"));
data.add(entityTest);
}
// 計算總頁數
Integer pages = (int)Math.ceil(total * 1.0 / pageSize);
// 封裝查詢結果
pageReSult.setTotal(total);
pageReSult.setPages(pages);
pageReSult.setPageNum(pageNum);
pageReSult.setData(data);
pageReSult.setPageNum(pageNum);
} catch (SQLException e) {
throw new RuntimeException("分頁查詢錯誤!");
}
// 使用工具類返回查詢結果
CommonResult.success(resp, pageReSult);
}
}
每頁查詢3條資料,測試結果如下:
第一頁資料,重點看id為1,2,3.
第二頁資料,id為4,5,6
如果每頁查詢5條資料,查詢第二頁結果也正確。到此Java後端分頁查詢功能全部實現。有其他建議的小夥伴,歡迎留言討論。