分页原理浅析
1.關(guān)于分頁(yè)
只討論分頁(yè),即顯示數(shù)據(jù),不做任何過濾(搜索)和排序,僅僅是顯示數(shù)據(jù)
?
1.1hibernate的分頁(yè)
mysql用limit來(lái)作分頁(yè),核心參數(shù)有兩個(gè),start與size,即開始的位置與每頁(yè)顯示的數(shù)量,但是我們?cè)谟胔ibernate時(shí)發(fā)現(xiàn)使用他提供的
setFirstResult((page-1)*pageSize).setMaxResults(pageSize)也可以完成分頁(yè)
解釋下page和pageSize,page表示當(dāng)前頁(yè),也就是當(dāng)前是第多少頁(yè),pageSize依然表示本頁(yè)的數(shù)據(jù)量
page與start的關(guān)系為start=(page-1)*pageSize,以每頁(yè)2條數(shù)據(jù)為例,
select * from table limit 0,2 ---->第一頁(yè)數(shù)據(jù)是 1,2 start=0,page=1
select * from table limit 2,2 ---->第二頁(yè)數(shù)據(jù)是 3,4 start=2,page=2
select * from table limit 4,2 ---->第三頁(yè)數(shù)據(jù)是 5,6 start=4,page=3
.....
setFirstResult() -->從哪開始查
setMaxResults() -->查多少
?
1.2 實(shí)際使用
1.2.1 以jquery DataTable分頁(yè)為例
真正開發(fā)的時(shí)候我們顯示數(shù)據(jù)的時(shí)候,往往使用各種分頁(yè)插件,他們的分頁(yè)略有不同,但原理都是一樣的,即通過點(diǎn)擊頁(yè)碼,觸發(fā)ajax,發(fā)送當(dāng)前頁(yè)碼(page)以及本頁(yè)要顯示的數(shù)據(jù)量(pageSize)給
后臺(tái)處理,以jquery DataTable為例, 其發(fā)送給后臺(tái)的參數(shù)就有start,代表第一條數(shù)據(jù)的起始位置比如 0代表第一條數(shù)據(jù),當(dāng)然還有l(wèi)ength,但是你可能會(huì)見到這種寫法,這種寫法是公式的反推:page=(start / length) +1,先利用DataTable的ajax向servlet發(fā)送請(qǐng)求,發(fā)送的信息如下圖
?
事實(shí)上沒有必要再去計(jì)算出page,因?yàn)镈ataTable主動(dòng)提供了start參數(shù),這里通過打印的形式來(lái)再次證明start與page的關(guān)系,(每頁(yè)顯示數(shù)據(jù)設(shè)置為2)?與我們上面1.1所寫的相互對(duì)照,發(fā)現(xiàn)打印的結(jié)果沒什么問題
具體使用請(qǐng)參考https://www.cnblogs.com/tele-share/p/8667434.html
?
1.2.2 以bootstrap-paginator為例
然而大多數(shù)情況下,分頁(yè)插件不會(huì)直接提供start,只會(huì)提供page參數(shù)(因?yàn)閷?duì)于一個(gè)插件來(lái)說(shuō),告訴你現(xiàn)在是第幾頁(yè)更加直接明了),比如bootstrap-paginator,這個(gè)時(shí)候你可以現(xiàn)在前臺(tái)計(jì)算出start然后傳遞start和size或者傳遞page和size,在后臺(tái)進(jìn)行計(jì)算
(事實(shí)上在使用bootstrap-paginator的時(shí)候你需要兩次ajax,第一次查詢數(shù)據(jù)量,第二次才是顯示數(shù)據(jù))
具體使用請(qǐng)參考http://www.cnblogs.com/tele-share/p/8982910.html
?
通過上面的分析我們可以發(fā)現(xiàn)分頁(yè)的核心參數(shù)是start和size,page,但是僅僅有這兩個(gè)參數(shù)顯然還不夠
?
1.2.3封裝Page類(顯示用的DataTable)
當(dāng)你使用分頁(yè)插件的時(shí)候,不可避免的要去顯示""共計(jì)有多少條記錄","共計(jì)多少頁(yè)",此外你必須告訴你的分頁(yè)插件,你的數(shù)據(jù)總量,總頁(yè)數(shù)以及你每次查詢到的本頁(yè)的結(jié)果集,用戶輸入的關(guān)鍵詞在切換到下一頁(yè)
時(shí)是要仍然需要顯示在搜索框中,經(jīng)過以上的分析我們發(fā)現(xiàn)這個(gè)時(shí)候封裝一個(gè)Page類就很有必要了(當(dāng)然不封裝也可以),這個(gè)page類通常包括這些屬性:總頁(yè)數(shù),總頁(yè)碼,當(dāng)前頁(yè),每頁(yè)顯示數(shù)據(jù),關(guān)鍵詞,搜索的域
以及查詢到的結(jié)果集.
1 /* 2 * 分頁(yè)對(duì)象 3 * 4 */ 5 public class Page<T> { 6 private Integer pageSize;//每頁(yè)顯示條數(shù) 7 private Integer page;//當(dāng)前頁(yè) 8 private Integer pageTotal;//總頁(yè)數(shù)----->用于顯示當(dāng)前共多少頁(yè) 9 private Integer recordsTotal;//總記錄數(shù)----->顯示當(dāng)前共有多少條記錄 10 private String keywords;//關(guān)鍵字 假設(shè)只有一個(gè) 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(關(guān)鍵字),fields(搜索域),這二者構(gòu)成了查詢條件,接下來(lái)首先要根據(jù)關(guān)鍵字和域?qū)ο笕ゲ樵兛偭?得到總數(shù)據(jù)量后要來(lái)計(jì)算總頁(yè)數(shù)
總頁(yè)數(shù)可以用Math中的ceil()方法來(lái)計(jì)算,當(dāng)然if else也可以
1 //封裝page對(duì)象 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);//查詢的每頁(yè)的結(jié)果集 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 }如果你是從數(shù)據(jù)庫(kù)取數(shù)據(jù)的話到這個(gè)地方難點(diǎn)已經(jīng)解決完了,因?yàn)檫@些分頁(yè)參數(shù)你都有了,接下來(lái)只要傳參數(shù)給數(shù)據(jù)庫(kù)就好了,但如果你沒有使用數(shù)據(jù)庫(kù),你的數(shù)據(jù)是采集到本地磁盤上,然后用lucene建立索引庫(kù)查詢的話,你還要自己實(shí)現(xiàn)底層的分頁(yè)方法,底層的分頁(yè)處理,應(yīng)當(dāng)是遍歷查詢出的結(jié)果集然后封裝每一頁(yè)的數(shù)據(jù),以下是偽代碼
1 List list = new ArrayList(); 2 List<Document> docList = search(query);//docList是查詢的總數(shù)據(jù)集 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 }這樣做完之后,這個(gè)list里面就是每一頁(yè)的數(shù)據(jù)了
?
總結(jié):
1.封裝page類有時(shí)并不是很必要,里面的一些屬性,也是看情況添加,但只要你封裝Page對(duì)象,那么page和pageSize這兩個(gè)屬性少不了的
2.分頁(yè)插件多種多樣,各種參數(shù)眼花繚亂,但一些參數(shù)很固定,如總數(shù)據(jù)量,總頁(yè)數(shù),當(dāng)前頁(yè),每頁(yè)數(shù)據(jù)量等,把這些參數(shù)處理好,分頁(yè)基本就ok了
轉(zhuǎn)載于:https://www.cnblogs.com/tele-share/p/9174926.html
總結(jié)
- 上一篇: a:hover伪类在ios移动端浏览器内
- 下一篇: 利用vue-resource模拟百度下拉