春風博客

          春天里,百花香...

          導航

          <2008年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          統計

          公告

          MAIL: junglesong@gmail.com
          MSN: junglesong_5@hotmail.com

          Locations of visitors to this page

          常用鏈接

          留言簿(11)

          隨筆分類(224)

          隨筆檔案(126)

          個人軟件下載

          我的其它博客

          我的鄰居們

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          分頁技術及其實現

          什么是分頁技術

          分頁,是一種將所有數據分段展示給用戶的技術.用戶每次看到的不是全部數據,而是其中的一部分,如果在其中沒有找到自習自己想要的內容,用戶可以通過制定頁碼或是翻頁的方式轉換可見內容,直到找到自己想要的內容為止.其實這和我們閱讀書籍很類似.

          下頁顯示了兩種常見的分頁方式.


          分頁的意義

          分頁確實有效,但它一定會加大系統的復雜度,但可否不分頁呢?如果數據量少的話當然可以.但是對于企業信息系統來說數據量不會限制在一個小范圍內.如果不顧一切的Select * from某個表,再將返回的數據一古腦的扔給客戶,即使客戶能夠忍受成千上萬足夠讓人眼花繚亂的表格式數據,繁忙的網絡,緊張的服務器也會提出它們無聲的抗議,甚至有時會以徹底的罷工作為終結.這個結局有點像古代為所欲為的暴君和他忍無可忍的臣民之間的故事.
          程序員不是暴君,他希望程序使生活變得更好而不是更糟.考慮到企業信息系統多是三層甚至更多層架構的事實,程序員在向客戶展示數據時都應該采取分頁的形式.如果他不想被抱怨淹沒或是半夜被電話驚醒的話.

          從請求發起到返回數據的整個過程

          現在你已經下定決心想要分頁了,在動手書寫代碼之前,先讓我們回想一下,在典型的三層架構中,從請求發起到返回數據的整個過程.如下所示:


          在哪里進行分頁

          從上面的圖中我們可以觀察得知,在SQL語句處理完畢后,數據庫,WebApplication和Browser都能進行分頁,那在哪里分頁好呢?
          判斷的標準是速度,顯而易見,數據庫服務器,Web應用服務器和客戶端之間是網絡,如果網絡傳遞的數據量越少,則客戶端獲得響應的速度越快.而且一般來說,數據庫服務器和Web應用服務器的處理能力一般比客戶端要強很多.從這兩點來看,在客戶端分頁的方案是最不可取的.
          其次就剩下了在Web服務器端分頁和在數據庫端分頁兩種方式了,如果選擇在Web服務器端分頁的話,大部分的被過濾掉的數據還是被傳輸到了Web應用服務器端,與其這樣還不如直接在數據庫端進行分頁.

          分頁的SQL語句

          如果我們是通過JDBC的方式訪問數據庫,那么就有必要根據數據庫類型采取不同的SQL分頁語句,對于MySql數據庫,我們可以采用limit語句進行分頁,對于Oracle數據庫,我們可以采用rownum的方式進行分頁.

          MySql的Limit m,n語句

          Limit后的兩個參數中,參數m是起始下標,它從0開始;參數n是返回的記錄數。我們需要分頁的話指定這兩個值即可.
          如右是limit語句的一次應用,圖示的SQL語句返回報銷記錄表中第四,第五條報銷額度最大的記錄。


          Oracle數據庫的rownum

          在Oracle數據庫中,分頁方式沒有MySql這樣簡單,它需要依靠rownum來實現.
          Rownum表示一條記錄的行號,值得注意的是它在獲取每一行后才賦予.因此,想指定rownum的區間來取得分頁數據在一層查詢語句中是無法做到的,要分頁還要進行一次查詢.
          右圖是分頁的具體示例,它從帳戶表中返回前十條記錄.


          將兩種方案統合起來

          實際上兩種方案的核心查詢語句,分頁的起點和終點都是一樣的,只是方言有所不同.如果將特殊的部分封裝起來,對外置以統一的接口,這樣在轉換數據庫時更換被/* */屏蔽的部分即可.
          下頁顯示了統合的函數.

          List<BaseDomainObj> fetchPageRecords(int start,int end,String coreSql) throws CannotConnectToDBException,SQLException{
            StringBuffer sb
          =new StringBuffer();
            
            
          // 下面是Oracle的分頁
            /*sb.append(" Select                              ");
            sb.append("        *                            ");
            sb.append(" from                                ");
            sb.append("        (                            ");
            sb.append("         Select                      ");
            sb.append("                t01.*,               ");
            sb.append("                rownum as newRowNum  ");
            sb.append("         from                        ");
            sb.append("                (                    ");
            sb.append(coreSql);
            sb.append("                ) t01                ");
            sb.append("         where                       ");
            sb.append("                rownum<='"+end+"'    ");
            sb.append("        )                            ");
            sb.append(" where                               ");
            sb.append("        newRowNum>'"+start+"'        ");
          */

            
            
          // 下面是MySql的分頁
            sb.append(coreSql+" limit "+start+","+end);
            
            String sql
          =sb.toString();   
            
          return search(sql);
          }

           

          Hibernate實現的分頁

          如果使用Hibernate取代JDBC,那么上面這一步就不用我們自己費力了,Hiberate會根據方言的種類選擇不同的方案,具體我們不必知道也不想知道,要分頁直接制定firstRow和maxRow即可,具體函數如下:

          public List<T> findPageDatum(String hql,int firstRow,int maxRow){
                List
          <T> result;
            
                Session session
          =HibernateUtil.getSession();

                Query q 
          = session.createQuery(hql);
                q.setFirstResult(firstRow);
                q.setMaxResults(maxRow);
                result 
          =(List<T>) q.list(); 

                session.flush();
                HibernateUtil.closeSession(session);
                
                
          return result;
          }


           

          posted on 2008-09-13 19:20 sitinspring 閱讀(10308) 評論(2)  編輯  收藏 所屬分類: Web開發

          評論

          # re: 分頁技術及其實現 2008-09-13 22:10 esmiles

          不錯,基本我們的項目中也是這么實現的。只不過有個問題比較郁悶,就是為了得到記錄總數總是要count(*)一下。  回復  更多評論   

          # re: 分頁技術及其實現 2008-09-20 16:57 robben

          不錯  回復  更多評論   

          sitinspring(http://www.aygfsteel.com)原創,轉載請注明出處.
          主站蜘蛛池模板: 延长县| 阿拉善盟| 岚皋县| 华安县| 龙游县| 杭锦后旗| 开远市| 浮山县| 岑巩县| 碌曲县| 房产| 屯留县| 喀喇沁旗| 孝感市| 天全县| 泾川县| 柳江县| 新沂市| 行唐县| 留坝县| 沙坪坝区| 宜丰县| 常山县| 祥云县| 花垣县| 芮城县| 丹寨县| 鸡东县| 康定县| 涟水县| 盐源县| 教育| 黄浦区| 射洪县| 碌曲县| 和林格尔县| 高要市| 花垣县| 株洲市| 泸州市| 江北区|