1. 程式人生 > 其它 >java分頁的實現,外掛PageHelper的使用及原理

java分頁的實現,外掛PageHelper的使用及原理

java分頁的實現,外掛PageHelper的使用及原理
https://blog.csdn.net/qq_25498677/article/details/69675664

如果你只希望知道PageHelper的用法,直接去github檢視官網文件 Mybatis-PageHelper.

 

1.關於分頁。

web專案中,分頁是一個常見的功能。在我剛學完javaweb的時候在沒有用任何框架的情況下做過分頁,程式碼非常的冗餘、難看,後臺每個POJO類的增刪改查裡都需要寫:(pageSize為每頁大小,pageNum為查詢的頁數)

 

  1. getList(int
    pageSize,int pageNum);
  2. getTotal();

 

而前端也要寫多個jsp,一個分頁就對應了一個jsp。導致不管是前後臺,程式碼都大量重複,實在是太不優雅了。

 

2.PageHelper的優缺點。

PageHelper做的是什麼呢?它封裝了分頁的後臺部分,說得更簡單點,就是你不需要每個POJO類的增刪改查裡都包括那兩個方法了,它幫你做了。你只需要有一個selectAll的方法,它會根據你使用的資料庫來將你selectAll的sql改裝成一個分頁查詢的sql,並順帶生成一個查詢總數的sql。

如圖,對應不同的資料庫有不同的方言,如常見的Mysql,分頁關鍵字是limit,它就是這樣組裝你的sql。

 

  1. @Override
  2. public String getPageSql(String sql, Page page, CacheKey pageKey) {
  3. StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
  4. sqlBuilder.append(sql);
  5. if (page.getStartRow() == 0) {
  6. sqlBuilder.append(" LIMIT ");
  7. sqlBuilder.append(page.getPageSize());
  8. } else {
  9. sqlBuilder.append(" LIMIT ");
  10. sqlBuilder.append(page.getStartRow());
  11. sqlBuilder.append(",");
  12. sqlBuilder.append(page.getPageSize());
  13. pageKey.update(page.getStartRow());
  14. }
  15. pageKey.update(page.getPageSize());
  16. return sqlBuilder.toString();
  17. }

 

 

 

PageHelper不僅幫你分頁查詢了資料,在返回時直接返回Page物件,裡更是封裝了許多分頁資訊。但是在前後臺json資料互動時,由於Page物件繼承自ArrayList,json不會保留其分頁資訊,所以在使用時往往是這樣使用的:

 

  1. @Override
  2. public PageInfo<TopicPost> selectAllPublicTopicPost(int pageNum) {
  3. int pageSize = 10;
  4. PageInfo<TopicPost> topicPostList = new PageInfo<TopicPost>();//主題帖表
  5. try {
  6. PageHelper.startPage(pageNum, pageSize);
  7. topicPostList = ((Page<TopicPost>)topicPostDao.daoSelectAllPublicTopicPost()).toPageInfo();
  8. } catch (Exception e) {
  9. log.error("查詢狀態正常的主題帖失敗!"+e.toString());
  10. e.printStackTrace();
  11. }
  12. return topicPostList;
  13. }


即將查詢出來的Page轉為PageInfo(沒有繼承ArrayList),將你的PageInfo<Object>返回給前臺就可以了。

 

 

至此,我們可以看到PageHelper的優缺點。

優點:封裝分頁sql,使我們不需要每個地方都去寫分頁的查詢語句;同時,使我們select的sql語句向下相容,換了資料庫也不需要更改sql程式碼;

缺點:自帶的Page物件轉json時會丟失分頁資料;而轉為PageInfo物件時分頁資訊過多(這一點作者已在github上說明,建議自己實現PageInfo)

 

3.前端的實現。

在拿到後臺傳來的資料後,前端要做的要不少。考慮一個這樣的分頁: 

<<  <  1  2  3  4  5  >  >>   難點在中間的五個數字,通常情況下PageNum(當前你瀏覽的頁數)在中間,每當翻頁時五個數字都會發生變化,但如果總頁數較小或者PageNum較小時則不一定發生變動,同時還需要注意總頁數小於5的問題。

<< 為到第一頁

<   為上一頁

 firstNum 通常為PageNum - 2

 secondNum 通常為PageNum - 1

 thirdNum 通常為PageNum

 fourthNum 通常為PageNum + 1

 fifthNum 通常為PageNum + 2

>   為下一頁

>>為最後一頁

直接看程式碼:

 

  1. //檢視所有狀態正常的主題帖
  2. function selectAllPublicTopicPost(pageNum){
  3. var url = "/guestbook/rs/topicpost/selectallpublictopicpost";
  4. var json = JSON.stringify(pageNum);
  5. $.ajax({
  6. url:url,
  7. type:'POST',
  8. async:true,
  9. data: json,
  10. contentType:"application/json",
  11. dataType:'json',
  12. success:function(data,textStatus,jqXHR){
  13. var firstNum = pageNum - 2;
  14. var secondNum = pageNum -1;
  15. var thirdNum = pageNum;
  16. var fourthNum = pageNum + 1;
  17. var fifthNum = pageNum + 2;
  18. var prePage = pageNum - 1;
  19. var nextPage = pageNum + 1;
  20. if(pageNum < 4 || data.pages < 6){
  21. firstNum = 1;
  22. secondNum = 2;
  23. thirdNum = 3;
  24. fourthNum = 4;
  25. fifthNum = 5;
  26. }
  27. else if(pageNum > data.pages-2){
  28. firstNum = data.pages-4;
  29. secondNum = data.pages-3;
  30. thirdNum = data.pages-2;
  31. fourthNum = data.pages-1;
  32. fifthNum = data.pages;
  33. }
  34. if(data.isFirstPage){
  35. prePage = 1;
  36. }
  37. if(data.isLastPage ){
  38. nextPage = data.pages;
  39. }
  40. var index_page = "<li><a onclick='selectAllPublicTopicPost(1)' aria-label='Previous'><span aria-hidden='true'><<</span></a></li>"
  41. +"<li><a onclick='selectAllPublicTopicPost("+prePage+")' aria-label='Previous'><span aria-hidden='true'><</span></a></li>"
  42. +"<li><a onclick='selectAllPublicTopicPost("+firstNum+")'>"+firstNum+"</a></li>";
  43. if(secondNum <= data.pages){
  44. index_page = index_page + "<li><a onclick='selectAllPublicTopicPost("+secondNum+")'>"+secondNum+"</a></li>";
  45. }
  46. if(thirdNum <= data.pages){
  47. index_page = index_page + "<li><a onclick='selectAllPublicTopicPost("+thirdNum+")'>"+thirdNum+"</a></li>";
  48. }
  49. if(fourthNum <= data.pages){
  50. index_page = index_page + "<li><a onclick='selectAllPublicTopicPost("+fourthNum+")'>"+fourthNum+"</a></li>";
  51. }
  52. if(fifthNum <= data.pages){
  53. index_page = index_page + "<li><a onclick='selectAllPublicTopicPost("+fifthNum+")'>"+fifthNum+"</a></li>";
  54. }
  55. index_page = index_page +"<li><a onclick='selectAllPublicTopicPost("+nextPage+")' aria-label='Next'><span aria-hidden='true'>></span></a></li>"
  56. +"<li><a onclick='selectAllPublicTopicPost("+data.pages+")' aria-label='Next'><span aria-hidden='true'>>></span></a></li>";
  57. $("#index_page").html(index_page);
  58. //以下內容不重要
  59. var tp = "";
  60. jQuery.each( data.list,function(i,item){
  61. tp = tp + "<div class='col-lg-4'><a href='/guestbook/contents.html?topicPostId="
  62. +item.id
  63. +"' target='_blank'>"
  64. +item.title
  65. +"</a></div><div class='col-lg-2'>"
  66. +item.keyword
  67. +"</div><div class='col-lg-2'>"
  68. +vagueTime(new Date(item.time).toLocaleString())
  69. +"</div><div class='col-lg-2'><a href='/guestbook/cust_info.html?uid="
  70. +item.userId
  71. +"' target='_blank'>"
  72. +item.userName
  73. +"</a></div><div class='col-lg-1'>"
  74. +item.replyNumber
  75. +"<br/><br/></div>";
  76. });
  77. $("#topic_list").html(tp);
  78. }
  79. })
  80. }

這樣就是一個完整的分頁的前後臺實現,但前端依然是每一個分頁都要去寫這麼一大段程式碼,還有改善空間。

 

 

4.綜合解決方案。

後臺:採用PageHelper查詢出來的Page轉為PageInfo,如果需求的查詢功能比較簡單或者對效能要求高,自己照著PageInfo實現一個MyPageInfo,其中只要自己需要的屬性、方法即可。

前端:寫一個page.js提供一個getPageArr的方法,對傳來的做PageNum做處理,返回一個數組,即firstNum至fifthNum,當然,要注意資料庫不到5頁的返回哦。這樣的話前端也避免了冗餘程式碼。