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頁的返回哦。這樣的話前端也避免了冗余代碼。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM