1.關於分頁
只討論分頁,即顯示數據,不做任何過濾(搜索)和排序,僅僅是顯示數據
1.1hibernate的分頁
mysql用limit來作分頁,核心參數有兩個,start與size,即開始的位置與每頁顯示的數量,但是我們在用hibernate時發現使用他提供的
setFirstResult((page-1)*pageSize).setMaxResults(pageSize)也可以完成分頁
解釋下page和pageSize,page表示當前頁,也就是當前是第多少頁,pageSize依然表示本頁的數據量
page與start的關系為start=(page-1)*pageSize,以每頁2條數據為例,
select * from table limit 0,2 ---->第一頁數據是 1,2 start=0,page=1
select * from table limit 2,2 ---->第二頁數據是 3,4 start=2,page=2
select * from table limit 4,2 ---->第三頁數據是 5,6 start=4,page=3
.....
setFirstResult() -->從哪開始查
setMaxResults() -->查多少
1.2 實際使用
1.2.1 以jquery DataTable分頁為例
真正開發的時候我們顯示數據的時候,往往使用各種分頁插件,他們的分頁略有不同,但原理都是一樣的,即通過點擊頁碼,觸發ajax,發送當前頁碼(page)以及本頁要顯示的數據量(pageSize)給
后台處理,以jquery DataTable為例, 其發送給后台的參數就有start,代表第一條數據的起始位置比如 0代表第一條數據,當然還有length,但是你可能會見到這種寫法,這種寫法是公式的反推:page=(start / length) +1,先利用DataTable的ajax向servlet發送請求,發送的信息如下圖
事實上沒有必要再去計算出page,因為DataTable主動提供了start參數,這里通過打印的形式來再次證明start與page的關系,(每頁顯示數據設置為2) 與我們上面1.1所寫的相互對照,發現打印的結果沒什么問題
具體使用請參考https://www.cnblogs.com/tele-share/p/8667434.html
1.2.2 以bootstrap-paginator為例
然而大多數情況下,分頁插件不會直接提供start,只會提供page參數(因為對於一個插件來說,告訴你現在是第幾頁更加直接明了),比如bootstrap-paginator,這個時候你可以現在前台計算出start然后傳遞start和size或者傳遞page和size,在后台進行計算
(事實上在使用bootstrap-paginator的時候你需要兩次ajax,第一次查詢數據量,第二次才是顯示數據)
具體使用請參考http://www.cnblogs.com/tele-share/p/8982910.html
通過上面的分析我們可以發現分頁的核心參數是start和size,page,但是僅僅有這兩個參數顯然還不夠
1.2.3封裝Page類(顯示用的DataTable)
當你使用分頁插件的時候,不可避免的要去顯示""共計有多少條記錄","共計多少頁",此外你必須告訴你的分頁插件,你的數據總量,總頁數以及你每次查詢到的本頁的結果集,用戶輸入的關鍵詞在切換到下一頁
時是要仍然需要顯示在搜索框中,經過以上的分析我們發現這個時候封裝一個Page類就很有必要了(當然不封裝也可以),這個page類通常包括這些屬性:總頁數,總頁碼,當前頁,每頁顯示數據,關鍵詞,搜索的域
以及查詢到的結果集.
1 /*
2 * 分頁對象 3 * 4 */
5 public class Page<T> { 6 private Integer pageSize;//每頁顯示條數
7 private Integer page;//當前頁
8 private Integer pageTotal;//總頁數----->用於顯示當前共多少頁
9 private Integer recordsTotal;//總記錄數----->顯示當前共有多少條記錄
10 private String keywords;//關鍵字 假設只有一個
11 private String[] fields; 12 private List<T> list = new ArrayList<T>(); 13
14 public Integer getPageTotal() { 15 return pageTotal; 16 } 17 public void setPageTotal(Integer pageTotal) { 18 this.pageTotal = pageTotal; 19 } 20 public Integer getRecordsTotal() { 21 return recordsTotal; 22 } 23 public void setRecordsTotal(Integer recordsTotal) { 24 this.recordsTotal = recordsTotal; 25 } 26 public List<T> getList() { 27 return list; 28 } 29 public void setList(List<T> list) { 30 this.list = list; 31 } 32 public Integer getPageSize() { 33 return pageSize; 34 } 35 public void setPageSize(Integer pageSize) { 36 this.pageSize = pageSize; 37 } 38 public Integer getPage() { 39 return page; 40 } 41 public void setPage(Integer page) { 42 this.page = page; 43 } 44 public String getKeywords() { 45 return keywords; 46 } 47 public void setKeywords(String keywords) { 48 this.keywords = keywords; 49 } 50 public String[] getFields() { 51 return fields; 52 } 53 public void setFields(String[] fields) { 54 this.fields = fields; 55 } 56 }
在servlet中要接收page,pageSize,keywords(關鍵字),fields(搜索域),這二者構成了查詢條件,接下來首先要根據關鍵字和域對象去查詢總量,得到總數據量后要來計算總頁數
總頁數可以用Math中的ceil()方法來計算,當然if else也可以
1 //封裝page對象
2 @Override 3 public <T> Page<T> getPage(String keywords, String[] fields, Class clazz, int page, int pageSize) { 4 Page<T> pageBean = new Page<T>(); 5 pageBean.setKeywords(keywords); 6 pageBean.setFields(fields); 7 pageBean.setPageSize(pageSize); 8 pageBean.setPage(page); 9 int start = (page-1)*pageSize; 10 List list = this.Page(keywords, fields, clazz,start,pageSize);//查詢的每頁的結果集 11 pageBean.setList(list); 12 Integer recordsTotal = bookDao.getCount(keywords, fields); 13 pageBean.setRecordsTotal(recordsTotal); 14 Integer pageTotal = 0; 15 /*if(recordsTotal % pageSize == 0) { 16 pageTotal = recordsTotal / pageSize; 17 }else { 18 pageTotal = (recordsTotal / pageSize) + 1; 19 }*/
20 pageTotal = (int) Math.ceil(recordsTotal / pageSize);//向上取整
21 pageBean.setPageTotal(pageTotal); 22 return pageBean; 23 }
如果你是從數據庫取數據的話到這個地方難點已經解決完了,因為這些分頁參數你都有了,接下來只要傳參數給數據庫就好了,但如果你沒有使用數據庫,你的數據是采集到本地磁盤上,然后用lucene建立索引庫查詢的話,你還要自己實現底層的分頁方法,底層的分頁處理,應當是遍歷查詢出的結果集然后封裝每一頁的數據,以下是偽代碼
1 List list = new ArrayList(); 2 List<Document> docList = search(query);//docList是查詢的總數據集
3 int end = Math.min(start+size,docList.size());//也可以用if else判斷
4 for(int i=start;i<end;i++){ 5 Document document = docList.get(i); 6 Object object = document2javabean(document, clazz); 7 list.add(object); 8 }
這樣做完之后,這個list里面就是每一頁的數據了
總結:
1.封裝page類有時並不是很必要,里面的一些屬性,也是看情況添加,但只要你封裝Page對象,那么page和pageSize這兩個屬性少不了的
2.分頁插件多種多樣,各種參數眼花繚亂,但一些參數很固定,如總數據量,總頁數,當前頁,每頁數據量等,把這些參數處理好,分頁基本就ok了