春風(fēng)博客

          春天里,百花香...

          導(dǎo)航

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

          統(tǒng)計(jì)

          公告

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

          Locations of visitors to this page

          常用鏈接

          留言簿(11)

          隨筆分類(224)

          隨筆檔案(126)

          個(gè)人軟件下載

          我的其它博客

          我的鄰居們

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          分頁(yè)技術(shù)及其實(shí)現(xiàn)

          什么是分頁(yè)技術(shù)

          分頁(yè),是一種將所有數(shù)據(jù)分段展示給用戶的技術(shù).用戶每次看到的不是全部數(shù)據(jù),而是其中的一部分,如果在其中沒(méi)有找到自習(xí)自己想要的內(nèi)容,用戶可以通過(guò)制定頁(yè)碼或是翻頁(yè)的方式轉(zhuǎn)換可見(jiàn)內(nèi)容,直到找到自己想要的內(nèi)容為止.其實(shí)這和我們閱讀書(shū)籍很類似.

          下頁(yè)顯示了兩種常見(jiàn)的分頁(yè)方式.


          分頁(yè)的意義

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

          從請(qǐng)求發(fā)起到返回?cái)?shù)據(jù)的整個(gè)過(guò)程

          現(xiàn)在你已經(jīng)下定決心想要分頁(yè)了,在動(dòng)手書(shū)寫代碼之前,先讓我們回想一下,在典型的三層架構(gòu)中,從請(qǐng)求發(fā)起到返回?cái)?shù)據(jù)的整個(gè)過(guò)程.如下所示:


          在哪里進(jìn)行分頁(yè)

          從上面的圖中我們可以觀察得知,在SQL語(yǔ)句處理完畢后,數(shù)據(jù)庫(kù),WebApplication和Browser都能進(jìn)行分頁(yè),那在哪里分頁(yè)好呢?
          判斷的標(biāo)準(zhǔn)是速度,顯而易見(jiàn),數(shù)據(jù)庫(kù)服務(wù)器,Web應(yīng)用服務(wù)器和客戶端之間是網(wǎng)絡(luò),如果網(wǎng)絡(luò)傳遞的數(shù)據(jù)量越少,則客戶端獲得響應(yīng)的速度越快.而且一般來(lái)說(shuō),數(shù)據(jù)庫(kù)服務(wù)器和Web應(yīng)用服務(wù)器的處理能力一般比客戶端要強(qiáng)很多.從這兩點(diǎn)來(lái)看,在客戶端分頁(yè)的方案是最不可取的.
          其次就剩下了在Web服務(wù)器端分頁(yè)和在數(shù)據(jù)庫(kù)端分頁(yè)兩種方式了,如果選擇在Web服務(wù)器端分頁(yè)的話,大部分的被過(guò)濾掉的數(shù)據(jù)還是被傳輸?shù)搅薟eb應(yīng)用服務(wù)器端,與其這樣還不如直接在數(shù)據(jù)庫(kù)端進(jìn)行分頁(yè).

          分頁(yè)的SQL語(yǔ)句

          如果我們是通過(guò)JDBC的方式訪問(wèn)數(shù)據(jù)庫(kù),那么就有必要根據(jù)數(shù)據(jù)庫(kù)類型采取不同的SQL分頁(yè)語(yǔ)句,對(duì)于MySql數(shù)據(jù)庫(kù),我們可以采用limit語(yǔ)句進(jìn)行分頁(yè),對(duì)于Oracle數(shù)據(jù)庫(kù),我們可以采用rownum的方式進(jìn)行分頁(yè).

          MySql的Limit m,n語(yǔ)句

          Limit后的兩個(gè)參數(shù)中,參數(shù)m是起始下標(biāo),它從0開(kāi)始;參數(shù)n是返回的記錄數(shù)。我們需要分頁(yè)的話指定這兩個(gè)值即可.
          如右是limit語(yǔ)句的一次應(yīng)用,圖示的SQL語(yǔ)句返回報(bào)銷記錄表中第四,第五條報(bào)銷額度最大的記錄。


          Oracle數(shù)據(jù)庫(kù)的rownum

          在Oracle數(shù)據(jù)庫(kù)中,分頁(yè)方式?jīng)]有MySql這樣簡(jiǎn)單,它需要依靠rownum來(lái)實(shí)現(xiàn).
          Rownum表示一條記錄的行號(hào),值得注意的是它在獲取每一行后才賦予.因此,想指定rownum的區(qū)間來(lái)取得分頁(yè)數(shù)據(jù)在一層查詢語(yǔ)句中是無(wú)法做到的,要分頁(yè)還要進(jìn)行一次查詢.
          右圖是分頁(yè)的具體示例,它從帳戶表中返回前十條記錄.


          將兩種方案統(tǒng)合起來(lái)

          實(shí)際上兩種方案的核心查詢語(yǔ)句,分頁(yè)的起點(diǎn)和終點(diǎn)都是一樣的,只是方言有所不同.如果將特殊的部分封裝起來(lái),對(duì)外置以統(tǒng)一的接口,這樣在轉(zhuǎn)換數(shù)據(jù)庫(kù)時(shí)更換被/* */屏蔽的部分即可.
          下頁(yè)顯示了統(tǒng)合的函數(shù).

          List<BaseDomainObj> fetchPageRecords(int start,int end,String coreSql) throws CannotConnectToDBException,SQLException{
            StringBuffer sb
          =new StringBuffer();
            
            
          // 下面是Oracle的分頁(yè)
            /*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的分頁(yè)
            sb.append(coreSql+" limit "+start+","+end);
            
            String sql
          =sb.toString();   
            
          return search(sql);
          }

           

          Hibernate實(shí)現(xiàn)的分頁(yè)

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

          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 閱讀(10310) 評(píng)論(2)  編輯  收藏 所屬分類: Web開(kāi)發(fā)

          評(píng)論

          # re: 分頁(yè)技術(shù)及其實(shí)現(xiàn) 2008-09-13 22:10 esmiles

          不錯(cuò),基本我們的項(xiàng)目中也是這么實(shí)現(xiàn)的。只不過(guò)有個(gè)問(wèn)題比較郁悶,就是為了得到記錄總數(shù)總是要count(*)一下。  回復(fù)  更多評(píng)論   

          # re: 分頁(yè)技術(shù)及其實(shí)現(xiàn) 2008-09-20 16:57 robben

          不錯(cuò)  回復(fù)  更多評(píng)論   

          sitinspring(http://www.aygfsteel.com)原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處.
          主站蜘蛛池模板: 楚雄市| 寿宁县| 崇明县| 琼海市| 开平市| 潍坊市| 名山县| 扎鲁特旗| 辛集市| 钦州市| 河曲县| 修武县| 温宿县| 杭锦旗| 东乌珠穆沁旗| 吴桥县| 北京市| 长子县| 台中县| 镇安县| 西林县| 公安县| 亳州市| 阿合奇县| 丰宁| 石台县| 汉阴县| 奉贤区| 托克逊县| 平乐县| 定西市| 永嘉县| 柳江县| 女性| 涡阳县| 海丰县| 宜良县| 体育| 漳浦县| 宜昌市| 舞阳县|