分頁查詢與展示
在web項目中經常會有需要展示某個表中所有數據的需求,例如下面的場景:

這個功能實現很簡單,在MVC+DAO的結構下,為DAO增加一個查詢所有的方法,執行select *from xxx
就可以獲取所有數據
問題
當表中數據很多時(成千上萬),會不會有問題?
這個問題可以分階段來思考:
-
DAO層是否能夠一次性從數據庫查詢出所有數據?
-
從數據庫返回后,JVM內存是否能夠保存這么多?
-
View層是否能一次性顯示全部?
-
第一個問題,由於數據庫底層存儲的是一堆字符串,所以單條數據通常不會占用太多空間,但是一旦數據量超過十萬級,數據大小也會在100MB左右,數據庫底層走的是TCP鏈接,傳輸100MB左右的數據需要一些時間,但是也不會太久,問題不大,除非數據量達到百萬千萬,我們且假設數據沒有這么多
-
第二個問題,寫個程序創建10w個對象看看行不行,速度很快,看起來問題不大
-
第三個問題,在頁面上顯示10w個圖片試試

打開頁面直接卡死了..
好吧,傻不拉幾的測試過程結束了
最后的結論是客戶端無法一次性展示過多數據,
另外即使一次性真的可以顯示這么多,用戶的使用體驗其實也是很差的,眼花繚亂...
分頁查詢與展示
分頁查詢與展示就是用來解決上述問題
問題的根本原因就在於一次性展示的數據太多,那么解決方案也就是一次性顯示一部分數據,這也是分頁展示的本質
實現分頁:
在MySQL中可以通過limit來對查詢結果進行分段
SQL語法:
select *from tableName limit st,n;
參數解析:
st表示查詢的起始位置,注意從0開始
n表示需要查詢的記錄條數
案例:
每頁顯示3條數據
#如上述顯示第一頁的第1-3條數據,sql語句為:
select *from food limit 0,3;
#第二頁第4-6條數據,sql語句為
select *from food limit 3,3;
#第三頁第4-6條數據,sql語句為
select *from food limit 6,3;
計算起始位置:
可以發現n的值是固定的不會變,但是st的值一直變
開發中不可能在sql中把st的值寫死,需要根據當前的頁碼(第幾頁)來進行計算,
公式:
#設當前頁碼為 p 每頁條數為 n
st = (p-1) * n
#即當前頁碼減去1 乘以每頁條數
計算總頁數:
通常還需要顯示頁碼進度當前頁碼/總頁數
在計算總頁數時必須先獲取數據的總條數,借助聚合函數count來實現
sql語法:
select count(*) from tableName;
有了總條數后,就可以除以每頁條數來得到總頁數
公式:
#設總條數為 c 每頁條數為 n 從頁數為tp
tp = c / n
需要注意的是如果有小數,那么需要向上取整,例如總條數10 每頁3條,10/3 = 3.3,意味着需要4頁才能全部顯示
ok到這里頁面上所有需要的數據都准備好了
總結一下:
-
要實現分頁的關鍵,在於使用limit關鍵字
-
頁面需提供兩個參數,當前頁碼, 每頁條數
-
DAO層需要提供兩個方法,獲取某頁的數據,獲取總頁數
請求交互流程
不分離:
需要注意的是由於請求對象是瞬時的,請求完成立即銷毀,所以JSP中的所有參數也就沒有了,我們必須維護當前的頁碼,在JSP和Servlet之間傳遞,這個問題在前后端分離時不存在,前端可以自己維護頁碼
分離:

SQL腳本:
#庫
create database db1 charset utf8;
#表
CREATE TABLE `food` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL,
`price` float DEFAULT NULL,
`unit` char(10) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `food` VALUES (1,'蘋果',5.8,'500g'),(2,'香蕉',3,'1kg'),(3,'橘子',4,'1kg'),(4,'橙子',6,'500g'),(5,'哈密瓜',8.5,'500g'),(6,'榴蓮',20,'500g'),(7,'雪蓮',4.5,'500g'),(8,'黃瓜',3,'500g'),(9,'辣椒',5.5,'500g'),(10,'葡萄',7,'500g');
源碼:
https://github.com/yangyuanhu/PagingShow.git