<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 13,  comments - 8,  trackbacks - 0
    目前比較廣泛使用的分頁方式是將查詢結果緩存在HttpSession或有狀態bean中,翻頁的時候從緩存中取出一頁數據顯示。這種方法有兩個主要的缺點:一是用戶可能看到的是過期數據;二是如果數據量非常大時第一次查詢遍歷結果集會耗費很長時間,并且緩存的數據也會占用大量內存,效率明顯下降。
      其它常見的方法還有每次翻頁都查詢一次數據庫,從ResultSet中只取出一頁數據(使用rs.last();rs.getRow()獲得總計錄條數,使用rs.absolute()定位到本頁起始記錄)。這種方式在某些數據庫(如oracle)的JDBC實現中差不多也是需要遍歷所有記錄,實驗證明在記錄數很大時速度非常慢。
      至于緩存結果集ResultSet的方法則完全是一種錯誤的做法。因為ResultSet在Statement或Connection關閉時也會被關閉,如果要使ResultSet有效勢必長時間占用數據庫連接。

      因此比較好的分頁做法應該是每次翻頁的時候只從數據庫里檢索頁面大小的塊區的數據。這樣雖然每次翻頁都需要查詢數據庫,但查詢出的記錄數很少,網絡傳輸數據量不大,如果使用連接池更可以略過最耗時的建立數據庫連接過程。而在數據庫端有各種成熟的優化技術用于提高查詢速度,比在應用服務器層做緩存有效多了。

      在oracle數據庫中查詢結果的行號使用偽列ROWNUM表示(從1開始)。例如select * from employee where rownum<10 返回前10條記錄。但因為rownum是在查詢之后排序之前賦值的,所以查詢employee按birthday排序的第100到120條記錄應該這么寫:
    [pre]        select * from (
                select my_table.*, rownum as my_rownum from (
                    select name, birthday from employee order by birthday
                ) my_table where rownum <120
            ) where my_rownum>=100
    [/pre]
      mySQL可以使用LIMIT子句:
        select name, birthday from employee order by birthday LIMIT 99,20
      DB2有rownumber()函數用于獲取當前行數。
      SQL Server沒研究過,可以參考這篇文章:http://www.csdn.net/develop/article/18/18627.shtm

      在Web程序中分頁會被頻繁使用,但分頁的實現細節卻是編程過程中比較麻煩的事情。大多分頁顯示的查詢操作都同時需要處理復雜的多重查詢條件,sql語句需要動態拼接組成,再加上分頁需要的記錄定位、總記錄條數查詢以及查詢結果的遍歷、封裝和顯示,程序會變得很復雜并且難以理解。因此需要一些工具類簡化分頁代碼,使程序員專注于業務邏輯部分。下面是我設計的兩個工具類:
      PagedStatement  封裝了數據庫連接、總記錄數查詢、分頁查詢、結果數據封裝和關閉數據庫連接等操作,并使用了PreparedStatement支持動態設置參數。
      RowSetPage  參考PetStore的page by page iterator模式, 設計RowSetPage用于封裝查詢結果(使用OracleCachedRowSet緩存查詢出的一頁數據,關于使用CachedRowSet封裝數據庫查詢結果請參考JSP頁面查詢顯示常用模式)以及當前頁碼、總記錄條數、當前記錄數等信息, 并且可以生成簡單的HTML分頁代碼。
      PagedStatement 查詢的結果封裝成RowsetPage。

      下面是簡單的使用示例
    1.     //DAO查詢數據部分代碼:
    2.     …
    3.     public RowSetPage getEmployee(String gender, int pageNo) throws Exception{
    4.         String sql="select emp_id, emp_code,  user_name, real_name from employee where gender =?";
    5.        //使用Oracle數據庫的分頁查詢實現,每頁顯示5條
    6.         PagedStatement pst =new PagedStatementOracleImpl(sql,  pageNo, 5);
    7.         pst.setString(1, gender);
    8.         return pst.executeQuery();
    9.     }
    10.     //Servlet處理查詢請求部分代碼:
    11.     …
    12.     int pageNo;
    13.     try{
    14.         //可以通過參數pageno獲得用戶選擇的頁碼
    15.         pageNo = Integer.parseInt(request.getParameter("pageno") );
    16.     }catch(Exception ex){
    17.         //默認為第一頁
    18.         pageNo=1;
    19.     }
    20.     String gender = request.getParameter("gender" );
    21.     request.setAttribute("empPage", myBean.getEmployee(gender, pageNo) );
    22.     …
    23.     //JSP顯示部分代碼
    24. <%@ page import = "page.RowSetPage"%>
    25.     …
    26.     <script language="javascript">
    27.         function doQuery(){
    28.             form1.actionType.value="doQuery";
    29.             form1.submit();
    30.     }
    31.     </script>
    32.     …
    33.     <form name=form1 method=get>
    34.       <input type=hidden name=actionType>
    35.       性別:
    36.       <input type=text name=gender size=1 value="<%=request.getParameter("gender")%>">
    37.       <input type=button value=" 查詢 " onclick="doQuery()">
    38. <%
    39.     RowSetPage empPage = (RowSetPage)request.getAttribute("empPage");
    40.     if (empPage == null ) empPage = RowSetPage.EMPTY_PAGE;
    41. %>
    42.     …
    43.     <table  cellspacing="0" width="90%">
    44.         <tr> <td>ID</td> <td>代碼</td> <td>用戶名</td> <td>姓名</td>  </tr>
    45. <%
    46.     javax.sql.RowSet empRS = (javax.sql.RowSet) empPage.getRowSet();
    47.     if (empRS!=nullwhile (empRS.next() ) {
    48. %>
    49.         <tr>  
    50.             <td><%= empRS.getString("EMP_ID")%></td> 
    51.             <td><%= empRS.getString("EMP_CODE")%></td>  
    52.             <td><%= empRS.getString("USER_NAME")%></td> 
    53.             <td><%= empRS.getString("REAL_NAME")%></td>  
    54.         </tr>
    55. <%
    56.     }// end while
    57. %>
    58.         <tr>
    59. <%
    60.     //顯示總頁數和當前頁數(pageno)以及分頁代碼。
    61.     //此處doQuery為頁面上提交查詢動作的javascript函數名, pageno為標識當前頁碼的參數名
    62. %>
    63.             <td colspan=4><%= empPage .getHTML("doQuery""pageno")%></td>
    64.         </tr>
    65.     </table>
    66.     </form>

      效果如圖:


      因為分頁顯示一般都會伴有查詢條件和查詢動作,頁面應已經有校驗查詢條件和提交查詢的javascript方法(如上面的doQuery),所以RowSetPage.getHTML()生成的分頁代碼在用戶選擇新頁碼時直接回調前面的處理提交查詢的javascript方法。注意在顯示查詢結果的時候上次的查詢條件也需要保持,如<input type=text name=gender size=1 value="<%=request.getParameter("gender")%>">。同時由于頁碼的參數名可以指定,因此也支持在同一頁面中有多個分頁區。
      另一種分頁代碼實現是生成每一頁的URL,將查詢參數和頁碼作為QueryString附在URL后面。這種方法的缺陷是在查詢條件比較復雜時難以處理,并且需要指定處理查詢動作的servlet,可能不適合某些定制的查詢操作。
      如果對RowSetPage.getHTML()生成的默認分頁代碼不滿意可以編寫自己的分頁處理代碼,RowSetPage提供了很多getter方法用于獲取相關信息(如當前頁碼、總頁數、 總記錄數和當前記錄數等)。
      在實際應用中可以將分頁查詢和顯示做成jsp taglib, 進一步簡化JSP代碼,屏蔽Java Code。

    附:分頁工具類的源代碼, 有注釋,應該很容易理解。

    1.Page.java
    2.RowSetPage.java(RowSetPage繼承Page)
    3.PagedStatement.java
    4.PagedStatementOracleImpl.java(PagedStatementOracleImpl繼承PagedStatement)



    您可以任意使用這些源代碼,但必須保留author evan_zhao@hotmail.com字樣
    1. ///////////////////////////////////
    2. //
    3. //  Page.java
    4. //  author: evan_zhao@hotmail.com
    5. //
    6. ///////////////////////////////////
    7. package page;
    8. import java.util.List;
    9. import java.util.ArrayList;
    10. import java.util.Collection;
    11. import java.util.Collections;
    12. /**
    13.  * Title: 分頁對象<br>
    14.  * Description:  用于包含數據及分頁信息的對象<br>
    15.  *               Page類實現了用于顯示分頁信息的基本方法,但未指定所含數據的類型,
    16.  *               可根據需要實現以特定方式組織數據的子類,<br>
    17.  *               如RowSetPage以RowSet封裝數據,ListPage以List封裝數據<br>
    18.  * Copyright:    Copyright (c) 2002 <br>
    19.  * @author evan_zhao@hotmail.com <br>
    20.  * @version 1.0
    21.  */
    22. public  class Page implements java.io.Serializable {
    23.     public static final Page EMPTY_PAGE = new Page();
    24.     public static final int  DEFAULT_PAGE_SIZE = 20;
    25.     public static final  int MAX_PAGE_SIZE = 9999;
    26.     private int myPageSize = DEFAULT_PAGE_SIZE;
    27.     private int start;
    28.     private int avaCount,totalSize;
    29.     private Object data;
    30.     private int currentPageno;
    31.     private int totalPageCount;
    32.     /**
    33.      * 默認構造方法,只構造空頁
    34.      */
    35.     protected Page(){
    36.         this.init(0,0,0,DEFAULT_PAGE_SIZE,new Object());
    37.     }
    38.     /**
    39.      * 分頁數據初始方法,由子類調用
    40.      * @param start 本頁數據在數據庫中的起始位置
    41.      * @param avaCount 本頁包含的數據條數
    42.      * @param totalSize 數據庫中總記錄條數
    43.      * @param pageSize 本頁容量
    44.      * @param data 本頁包含的數據
    45.      */
    46.     protected void init(int start, int avaCount, int totalSize, int pageSize, Object data){
    47.         this.avaCount =avaCount;
    48.         this.myPageSize = pageSize;
    49.         this.start = start;
    50.         this.totalSize = totalSize;
    51.         this.data=data;
    52.         //System.out.println("avaCount:"+avaCount);
    53.         //System.out.println("totalSize:"+totalSize);
    54.         if (avaCount>totalSize) {
    55.             //throw new RuntimeException("記錄條數大于總條數?!");
    56.         }
    57.         this.currentPageno = (start -1)/pageSize +1;
    58.         this.totalPageCount = (totalSize + pageSize -1) / pageSize;
    59.         if (totalSize==0 && avaCount==0){
    60.             this.currentPageno = 1;
    61.             this.totalPageCount = 1;
    62.         }
    63.         //System.out.println("Start Index to Page No: " + start + "-" + currentPageno);
    64.     }
    65.     public  Object getData(){
    66.         return this.data;
    67.     }
    68.     /**
    69.      * 取本頁數據容量(本頁能包含的記錄數)
    70.      * @return 本頁能包含的記錄數
    71.      */
    72.     public int getPageSize(){
    73.         return this.myPageSize;
    74.     }
    75.     /**
    76.      * 是否有下一頁
    77.      * @return 是否有下一頁
    78.      */
    79.     public boolean hasNextPage() {
    80.       /*
    81.         if (avaCount==0 && totalSize==0){
    82.             return false;
    83.         }
    84.         return (start + avaCount -1) < totalSize;
    85.        */
    86.       return (this.getCurrentPageNo()<this.getTotalPageCount());
    87.     }
    88.     /**
    89.      * 是否有上一頁
    90.      * @return  是否有上一頁
    91.      */
    92.     public boolean hasPreviousPage() {
    93.       /*
    94.         return start > 1;
    95.        */
    96.       return (this.getCurrentPageNo()>1);
    97.     }
    98.     /**
    99.      * 獲取當前頁第一條數據在數據庫中的位置
    100.      * @return
    101.      */
    102.     public int getStart(){
    103.         return start;
    104.     }
    105.     /**
    106.      * 獲取當前頁最后一條數據在數據庫中的位置
    107.      * @return
    108.      */
    109.     public int getEnd(){
    110.         int end = this.getStart() + this.getSize() -1;
    111.         if (end<0) {
    112.             end = 0;
    113.         }
    114.         return end;
    115.     }
    116.     /**
    117.      * 獲取上一頁第一條數據在數據庫中的位置
    118.      * @return 記錄對應的rownum
    119.      */
    120.     public int getStartOfPreviousPage() {
    121.         return Math.max(start-myPageSize, 1);
    122.     }
    123.     /**
    124.      * 獲取下一頁第一條數據在數據庫中的位置
    125.      * @return 記錄對應的rownum
    126.      */
    127.     public int getStartOfNextPage() {
    128.         return start + avaCount;
    129.     }
    130.     /**
    131.      * 獲取任一頁第一條數據在數據庫中的位置,每頁條數使用默認值
    132.      * @param pageNo 頁號
    133.      * @return 記錄對應的rownum
    134.      */
    135.     public static int getStartOfAnyPage(int pageNo){
    136.         return getStartOfAnyPage(pageNo, DEFAULT_PAGE_SIZE);
    137.     }
    138.     /**
    139.      * 獲取任一頁第一條數據在數據庫中的位置
    140.      * @param pageNo 頁號
    141.      * @param pageSize 每頁包含的記錄數
    142.      * @return 記錄對應的rownum
    143.      */
    144.     public static int getStartOfAnyPage(int pageNo, int pageSize){
    145.         int startIndex = (pageNo-1) * pageSize + 1;
    146.         if ( startIndex < 1) startIndex = 1;
    147.         //System.out.println("Page No to Start Index: " + pageNo + "-" + startIndex);
    148.         return startIndex;
    149.     }
    150.     /**
    151.      * 取本頁包含的記錄數
    152.      * @return 本頁包含的記錄數
    153.      */
    154.     public int getSize() {
    155.         return avaCount;
    156.     }
    157.     /**
    158.      * 取數據庫中包含的總記錄數
    159.      * @return 數據庫中包含的總記錄數
    160.      */
    161.     public int getTotalSize() {
    162.         return this.totalSize;
    163.     }
    164.     /**
    165.      * 取當前頁碼
    166.      * @return 當前頁碼
    167.      */
    168.     public int getCurrentPageNo(){
    169.         return  this.currentPageno;
    170.     }
    171.     /**
    172.      * 取總頁碼
    173.      * @return 總頁碼
    174.      */
    175.     public int getTotalPageCount(){
    176.         return this.totalPageCount;
    177.     }
    178.     /**
    179.      *
    180.      * @param queryJSFunctionName 實現分頁的JS腳本名字,頁碼變動時會自動回調該方法
    181.      * @param pageNoParamName 頁碼參數名稱
    182.      * @return
    183.      */
    184.     public String getHTML(String queryJSFunctionName, String pageNoParamName){
    185.         if (getTotalPageCount()<1){
    186.             return "<input type='hidden' name='"+pageNoParamName+"' value='1' >";
    187.         }
    188.         if (queryJSFunctionName == null || queryJSFunctionName.trim().length()<1) {
    189.             queryJSFunctionName = "gotoPage";
    190.         }
    191.         if (pageNoParamName == null || pageNoParamName.trim().length()<1){
    192.             pageNoParamName = "pageno";
    193.         }
    194.         String gotoPage = "_"+queryJSFunctionName;
    195.         StringBuffer html = new StringBuffer("\n");
    196.         html.append("<script language=\"Javascript1.2\">\n")
    197.              .append("function ").append(gotoPage).append("(pageNo){  \n")
    198.              .append(  "   var curPage=1;  \n")
    199.              .append(  "   try{ curPage = document.all[\"")
    200.              .append(pageNoParamName).append("\"].value;  \n")
    201.              .append(  "        document.all[\"").append(pageNoParamName)
    202.              .append("\"].value = pageNo;  \n")
    203.              .append(  "        ").append(queryJSFunctionName).append("(pageNo); \n")
    204.              .append(  "        return true;  \n")
    205.              .append(  "   }catch(e){ \n")
    206. //             .append(  "      try{ \n")
    207. //             .append(  "           document.forms[0].submit();  \n")
    208. //             .append(  "      }catch(e){   \n")
    209.              .append(  "          alert('尚未定義查詢方法:function ")
    210.              .append(queryJSFunctionName).append("()'); \n")
    211.              .append(  "          document.all[\"").append(pageNoParamName)
    212.              .append("\"].value = curPage;  \n")
    213.              .append(  "          return false;  \n")
    214. //             .append(  "      }  \n")
    215.              .append(  "   }  \n")
    216.              .append(  "}")
    217.              .append(  "</script>  \n")
    218.              .append(  "");
    219.         html.append( "<table  border=0 cellspacing=0 cellpadding=0 align=center width=80%>  \n")
    220.              .append( "  <tr>  \n")
    221.              .append( "    <td align=left><br>  \n");
    222.         html.append(  "       共" ).append( getTotalPageCount() ).append( "頁")
    223.              .append(  "       [") .append(getStart()).append("..").append(getEnd())
    224.              .append("/").append(this.getTotalSize()).append("]  \n")
    225.              .append( "    </td>  \n")
    226.              .append( "    <td align=right>  \n");
    227.         if (hasPreviousPage()){
    228.              html.append( "[<a href='javascript:").append(gotoPage)
    229.              .append("(") .append(getCurrentPageNo()-1) 
    230.              .append( ")'>上一頁</a>]   \n");
    231.         }
    232.         html.append(  "       第")
    233.              .append(   "        <select name='")
    234.              .append(pageNoParamName).append("' onChange='javascript:")
    235.              .append(gotoPage).append("(this.value)'>\n");
    236.         String selected = "selected";
    237.         for(int i=1;i<=getTotalPageCount();i++){
    238.             if( i == getCurrentPageNo() )
    239.                  selected = "selected";
    240.             else selected = "";
    241.             html.append( "      <option value='").append(i).append("' ")
    242.               .append(selected).append(">").append(i).append("</option>  \n");
    243.         }
    244.         if (getCurrentPageNo()>getTotalPageCount()){
    245.             html.append( "      <option value='").append(getCurrentPageNo())
    246.             .append("' selected>").append(getCurrentPageNo())
    247.             .append("</option>  \n");
    248.         }
    249.         html.append( "    </select>頁  \n");
    250.         if (hasNextPage()){
    251.              html.append( "    [<a href='javascript:").append(gotoPage)
    252.                .append("(").append((getCurrentPageNo()+1)) 
    253.                .append( ")'>下一頁</a>]   \n");
    254.         }
    255.         html.append( "</td></tr></table>  \n");
    256.         return html.toString();
    257.     }
    258. }
    259. ///////////////////////////////////
    260. //
    261. //  RowSetPage.java
    262. //  author: evan_zhao@hotmail.com
    263. //
    264. ///////////////////////////////////
    265. package page;
    266. import javax.sql.RowSet;
    267. /**
    268.  * <p>Title: RowSetPage</p>
    269.  * <p>Description: 使用RowSet封裝數據的分頁對象</p>
    270.  * <p>Copyright: Copyright (c) 2003</p>
    271.  * @author evan_zhao@hotmail.com
    272.  * @version 1.0
    273.  */
    274. public class RowSetPage extends Page {
    275.     private javax.sql.RowSet rs;
    276.     /**
    277.      *空頁
    278.      */
    279.     public static final RowSetPage EMPTY_PAGE = new RowSetPage();
    280.     /**
    281.      *默認構造方法,創建空頁
    282.      */
    283.     public RowSetPage(){
    284.       this(null, 0,0);
    285.     }
    286.     /**
    287.      *構造分頁對象
    288.      *@param crs 包含一頁數據的OracleCachedRowSet
    289.      *@param start 該頁數據在數據庫中的起始位置
    290.      *@param totalSize 數據庫中包含的記錄總數
    291.      */
    292.     public RowSetPage(RowSet crs, int start, int totalSize) {
    293.         this(crs,start,totalSize,Page.DEFAULT_PAGE_SIZE);
    294.     }
    295.     /**
    296.      *構造分頁對象
    297.      *@param crs 包含一頁數據的OracleCachedRowSet
    298.      *@param start 該頁數據在數據庫中的起始位置
    299.      *@param totalSize 數據庫中包含的記錄總數
    300.      *@pageSize 本頁能容納的記錄數
    301.      */
    302.     public RowSetPage(RowSet crs, int start, int totalSize, int pageSize) {
    303.         try{
    304.             int avaCount=0;
    305.             if (crs!=null) {
    306.                 crs.beforeFirst();
    307.                 if (crs.next()){
    308.                     crs.last();
    309.                     avaCount = crs.getRow();
    310.                 }
    311.                 crs.beforeFirst();
    312.             }
    313.             rs = crs;
    314.             super.init(start,avaCount,totalSize,pageSize,rs);
    315.         }catch(java.sql.SQLException sqle){
    316.             throw new RuntimeException(sqle.toString());
    317.         }
    318.     }
    319.     /**
    320.      *取分頁對象中的記錄數據
    321.      */
    322.     public javax.sql.RowSet getRowSet(){
    323.         return rs;
    324.     }
    325. }
    326. ///////////////////////////////////
    327. //
    328. //  PagedStatement.java
    329. //  author: evan_zhao@hotmail.com
    330. //
    331. ///////////////////////////////////
    332. package page;
    333. import foo.DBUtil;
    334. import java.math.BigDecimal;
    335. import java.util.List;
    336. import java.util.Iterator;
    337. import java.util.Collections;
    338. import java.sql.Connection;
    339. import java.sql.SQLException;
    340. import java.sql.ResultSet;
    341. import java.sql.Statement;
    342. import java.sql.PreparedStatement;
    343. import java.sql.Timestamp;
    344. import javax.sql.RowSet;
    345. /**
    346.  * <p>Title: 分頁查詢</p>
    347.  * <p>Description: 根據查詢語句和頁碼查詢出當頁數據</p>
    348.  * <p>Copyright: Copyright (c) 2002</p>
    349.  * @author evan_zhao@hotmail.com
    350.  * @version 1.0
    351.  */
    352. public abstract class PagedStatement {
    353.     public final static int MAX_PAGE_SIZE = Page.MAX_PAGE_SIZE;
    354.     protected String countSQL, querySQL;
    355.     protected int pageNo,pageSize,startIndex,totalCount;
    356.     protected javax.sql.RowSet rowSet;
    357.     protected RowSetPage rowSetPage;
    358.     private List boundParams;
    359.     /**
    360.      * 構造一查詢出所有數據的PageStatement
    361.      * @param sql  query sql
    362.      */
    363.     public PagedStatement(String sql){
    364.         this(sql,1,MAX_PAGE_SIZE);
    365.     }
    366.     /**
    367.      * 構造一查詢出當頁數據的PageStatement
    368.      * @param sql  query sql
    369.      * @param pageNo  頁碼
    370.      */
    371.     public PagedStatement(String sql, int pageNo){
    372.         this(sql, pageNo, Page.DEFAULT_PAGE_SIZE);
    373.     }
    374.     /**
    375.      * 構造一查詢出當頁數據的PageStatement,并指定每頁顯示記錄條數
    376.      * @param sql query sql
    377.      * @param pageNo 頁碼
    378.      * @param pageSize 每頁容量
    379.      */
    380.     public PagedStatement(String sql, int pageNo, int pageSize){
    381.         this.pageNo = pageNo;
    382.         this.pageSize = pageSize;
    383.         this.startIndex = Page.getStartOfAnyPage(pageNo, pageSize);
    384.         this.boundParams = Collections.synchronizedList(new java.util.LinkedList());
    385.         this.countSQL = "select count(*) from ( " + sql +") ";
    386.         this.querySQL = intiQuerySQL(sql, this.startIndex, pageSize);
    387.     }
    388.     /**
    389.      *生成查詢一頁數據的sql語句
    390.      *@param sql 原查詢語句
    391.      *@startIndex 開始記錄位置
    392.      *@size 需要獲取的記錄數
    393.      */
    394.     protected abstract  String intiQuerySQL(String sql, int startIndex, int size);
    395.     /**
    396.      *使用給出的對象設置指定參數的值
    397.      *@param index 第一個參數為1,第二個為2,。。。
    398.      *@param obj 包含參數值的對象
    399.      */
    400.     public void setObject(int index, Object obj) throws SQLException{
    401.         BoundParam bp = new BoundParam(index, obj);
    402.         boundParams.remove(bp);
    403.         boundParams.add( bp);
    404.     }
    405.     /**
    406.      *使用給出的對象設置指定參數的值
    407.      *@param index 第一個參數為1,第二個為2,。。。
    408.      *@param obj 包含參數值的對象
    409.      *@param targetSqlType 參數的數據庫類型
    410.      */
    411.     public void setObject(int index, Object obj, int targetSqlType) throws SQLException{
    412.         BoundParam bp = new BoundParam(index, obj, targetSqlType);
    413.         boundParams.remove(bp);
    414.         boundParams.add(bp );
    415.     }
    416.     /**
    417.      *使用給出的對象設置指定參數的值
    418.      *@param index 第一個參數為1,第二個為2,。。。
    419.      *@param obj 包含參數值的對象
    420.      *@param targetSqlType 參數的數據庫類型(常量定義在java.sql.Types中)
    421.      *@param scale 精度,小數點后的位數
    422.      * (只對targetSqlType是Types.NUMBER或Types.DECIMAL有效,其它類型則忽略)
    423.      */
    424.     public void setObject(int index, Object obj, int targetSqlType, int scale) throws SQLException{
    425.         BoundParam bp = new BoundParam(index, obj, targetSqlType, scale) ;
    426.         boundParams.remove(bp);
    427.         boundParams.add(bp);
    428.     }
    429.     /**
    430.      *使用給出的字符串設置指定參數的值
    431.      *@param index 第一個參數為1,第二個為2,。。。
    432.      *@param str 包含參數值的字符串
    433.      */
    434.     public void setString(int index, String str)throws SQLException{
    435.         BoundParam bp = new BoundParam(index, str)  ;
    436.         boundParams.remove(bp);
    437.         boundParams.add(bp);
    438.     }
    439.     /**
    440.      *使用給出的字符串設置指定參數的值
    441.      *@param index 第一個參數為1,第二個為2,。。。
    442.      *@param timestamp 包含參數值的時間戳
    443.      */
    444.     public void setTimestamp(int index, Timestamp timestamp)throws SQLException{
    445.         BoundParam bp = new BoundParam(index, timestamp)  ;
    446.         boundParams.remove(bp);
    447.         boundParams.add( bp );
    448.     }
    449.     /**
    450.      *使用給出的整數設置指定參數的值
    451.      *@param index 第一個參數為1,第二個為2,。。。
    452.      *@param value 包含參數值的整數
    453.      */
    454.     public void setInt(int index, int value)throws SQLException{
    455.         BoundParam bp =  new BoundParam(index, new Integer(value))  ;
    456.         boundParams.remove(bp);
    457.         boundParams.add( bp );
    458.     }
    459.     /**
    460.      *使用給出的長整數設置指定參數的值
    461.      *@param index 第一個參數為1,第二個為2,。。。
    462.      *@param value 包含參數值的長整數
    463.      */
    464.     public void setLong(int index, long value)throws SQLException{
    465.         BoundParam bp =  new BoundParam(index, new Long(value))  ;
    466.         boundParams.remove(bp);
    467.         boundParams.add( bp );
    468.     }
    469.     /**
    470.      *使用給出的雙精度浮點數設置指定參數的值
    471.      *@param index 第一個參數為1,第二個為2,。。。
    472.      *@param value 包含參數值的雙精度浮點數
    473.      */
    474.     public void setDouble(int index, double value)throws SQLException{
    475.         BoundParam bp =  new BoundParam(index, new Double(value))   ;
    476.         boundParams.remove(bp);
    477.         boundParams.add( bp);
    478.     }
    479.     /**
    480.      *使用給出的BigDecimal設置指定參數的值
    481.      *@param index 第一個參數為1,第二個為2,。。。
    482.      *@param bd 包含參數值的BigDecimal
    483.      */
    484.     public void setBigDecimal(int index, BigDecimal bd)throws SQLException{
    485.         BoundParam bp =   new BoundParam(index, bd )   ;
    486.         boundParams.remove(bp);
    487.         boundParams.add( bp);
    488.     }
    489.     private  void setParams(PreparedStatement pst) throws SQLException{
    490.         if (pst==null || this.boundParams==null || this.boundParams.size()==0 ) return ;
    491.         BoundParam param;
    492.         for (Iterator itr = this.boundParams.iterator();itr.hasNext();){
    493.             param = (BoundParam) itr.next();
    494.             if  (param==nullcontinue;
    495.             if (param.sqlType == java.sql.Types.OTHER){
    496.                 pst.setObject(param.index, param.value);
    497.             }else{
    498.                 pst.setObject(param.index, param.value, param.sqlType, param.scale);
    499.             }
    500.         }
    501.     }
    502.     /**
    503.      * 執行查詢取得一頁數據,執行結束后關閉數據庫連接
    504.      * @return RowSetPage
    505.      * @throws SQLException
    506.      */
    507.     public  RowSetPage executeQuery() throws SQLException{
    508.         System.out.println("executeQueryUsingPreparedStatement");
    509.         Connection conn = DBUtil.getConnection();
    510.         PreparedStatement pst = null;
    511.         ResultSet rs = null;
    512.         try{
    513.             pst = conn.prepareStatement(this.countSQL);
    514.             setParams(pst);
    515.             rs =pst.executeQuery();
    516.             if (rs.next()){
    517.                 totalCount = rs.getInt(1);
    518.             } else {
    519.                 totalCount = 0;
    520.             }
    521.             rs.close();
    522.             pst.close();
    523.             if (totalCount < 1 ) return RowSetPage.EMPTY_PAGE;
    524.             pst = conn.prepareStatement(this.querySQL);
    525.             System.out.println(querySQL);
    526.             pst.setFetchSize(this.pageSize);
    527.             setParams(pst);
    528.             rs =pst.executeQuery();
    529.             //rs.setFetchSize(pageSize);
    530.             this.rowSet = populate(rs);
    531.             rs.close();
    532.             rs = null;
    533.             pst.close();
    534.             pst = null;
    535.             this.rowSetPage = new RowSetPage(this.rowSet,startIndex,totalCount,pageSize);
    536.             return this.rowSetPage;
    537.         }catch(SQLException sqle){
    538.             //System.out.println("executeQuery SQLException");
    539.             sqle.printStackTrace();
    540.             throw sqle;
    541.         }catch(Exception e){
    542.             e.printStackTrace();
    543.             throw new RuntimeException(e.toString());
    544.         }finally{
    545.             //System.out.println("executeQuery finally");
    546.             DBUtil.close(rs, pst, conn);
    547.         }
    548.     }
    549.     /**
    550.      *將ResultSet數據填充進CachedRowSet
    551.      */
    552.     protected abstract RowSet populate(ResultSet rs) throws SQLException;
    553.     /**
    554.      *取封裝成RowSet查詢結果
    555.      *@return RowSet
    556.      */
    557.     public javax.sql.RowSet getRowSet(){
    558.         return this.rowSet;
    559.     }
    560.     /**
    561.      *取封裝成RowSetPage的查詢結果
    562.      *@return RowSetPage
    563.      */
    564.     public RowSetPage getRowSetPage() {
    565.         return this.rowSetPage;
    566.     }
    567.     /**
    568.      *關閉數據庫連接
    569.      */
    570.     public void close(){
    571.         //因為數據庫連接在查詢結束或發生異常時即關閉,此處不做任何事情
    572.         //留待擴充。
    573.     }
    574.     private class BoundParam {
    575.         int index;
    576.         Object value;
    577.         int sqlType;
    578.         int scale;
    579.         public BoundParam(int index, Object value) {
    580.             this(index, value, java.sql.Types.OTHER);
    581.         }
    582.         public BoundParam(int index, Object value, int sqlType) {
    583.             this(index, value, sqlType, 0);
    584.         }
    585.         public BoundParam(int index, Object value, int sqlType, int scale) {
    586.             this.index = index;
    587.             this.value = value;
    588.             this.sqlType = sqlType;
    589.             this.scale = scale;
    590.         }
    591.         public boolean equals(Object obj){
    592.             if (obj!=null && this.getClass().isInstance(obj)){
    593.                 BoundParam bp = (BoundParam)obj;
    594.                 if (this.index==bp.index) return true;
    595.             }
    596.             return false;
    597.         }
    598.     }
    599. }
    600. ///////////////////////////////////
    601. //
    602. //  PagedStatementOracleImpl.java
    603. //  author: evan_zhao@hotmail.com
    604. //
    605. ///////////////////////////////////
    606. package page;
    607. import java.sql.ResultSet;
    608. import java.sql.SQLException;
    609. import javax.sql.RowSet;
    610. import oracle.jdbc.rowset.OracleCachedRowSet;
    611. /**
    612.  * <p>Title: 分頁查詢Oracle數據庫實現</p>
    613.  * <p>Copyright: Copyright (c) 2002</p>
    614.  * @author evan_zhao@hotmail.com
    615.  * @version 1.0
    616.  */
    617. public class PagedStatementOracleImpl extends PagedStatement {
    618.     /**
    619.      * 構造一查詢出所有數據的PageStatement
    620.      * @param sql  query sql
    621.      */
    622.     public PagedStatementOracleImpl(String sql){
    623.         super(sql);
    624.     }
    625.     /**
    626.      * 構造一查詢出當頁數據的PageStatement
    627.      * @param sql  query sql
    628.      * @param pageNo  頁碼
    629.      */
    630.     public PagedStatementOracleImpl(String sql, int pageNo){
    631.         super(sql, pageNo);
    632.     }
    633.     /**
    634.      * 構造一查詢出當頁數據的PageStatement,并指定每頁顯示記錄條數
    635.      * @param sql query sql
    636.      * @param pageNo 頁碼
    637.      * @param pageSize 每頁容量
    638.      */
    639.     public PagedStatementOracleImpl(String sql, int pageNo, int pageSize){
    640.         super(sql, pageNo, pageSize);
    641.     }
    642.     /**
    643.      *生成查詢一頁數據的sql語句
    644.      *@param sql 原查詢語句
    645.      *@startIndex 開始記錄位置
    646.      *@size 需要獲取的記錄數
    647.      */
    648.     protected String intiQuerySQL(String sql, int startIndex, int size){
    649.         StringBuffer querySQL = new StringBuffer();
    650.         if (size != super.MAX_PAGE_SIZE) {
    651.             querySQL.append("select * from (select my_table.*,rownum as my_rownum from(")
    652.                     .append(  sql)
    653.                     .append(") my_table where rownum<").append(startIndex + size)
    654.                     .append(") where my_rownum>=").append(startIndex);
    655.         } else {
    656.             querySQL.append("select * from (select my_table.*,rownum as my_rownum from(")
    657.                     .append(sql)
    658.                     .append(") my_table ")
    659.                     .append(") where my_rownum>=").append(startIndex);
    660.         }
    661.         return querySQL.toString();
    662.     }
    663.     /**
    664.      *將ResultSet數據填充進CachedRowSet
    665.      */
    666.     protected  RowSet populate(ResultSet rs) throws SQLException{
    667.         OracleCachedRowSet ocrs = new OracleCachedRowSet();
    668.         ocrs.populate(rs);
    669.         return ocrs;
    670.     }
    671. }
    posted on 2005-10-26 18:35 YangRj 閱讀(333) 評論(0)  編輯  收藏 所屬分類: 精華文章
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(2)

    隨筆分類(5)

    隨筆檔案(13)

    文章分類(14)

    文章檔案(34)

    Apache - Tech Online

    BLOG 收集

    BLOG地址

    DB2

    Eclipse

    IBM - Tech Online

    JAVA

    ORACLE

    OS

    好網址

    文學網站

    累了 聽聽歌曲吧

    論壇

    積分與排名

    • 積分 - 25626
    • 排名 - 1515

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲欧洲专线一区| 国内精品免费视频精选在线观看| 一级免费黄色大片| 日韩视频免费在线| 亚洲激情电影在线| 伊人免费在线观看| 亚洲一级片内射网站在线观看| 国产亚洲中文日本不卡二区| 免费视频爱爱太爽了| 亚洲国产精品无码久久久秋霞2 | 日韩激情无码免费毛片| 国产成人无码免费看片软件| 亚洲人成无码www久久久| 色猫咪免费人成网站在线观看| 亚洲国产精品无码专区影院| 夜夜嘿视频免费看| 亚洲精品伊人久久久久| 97视频免费在线| 亚洲国产精品xo在线观看| 黄色成人网站免费无码av| 国产成人精品亚洲日本在线| 亚洲国产成人久久笫一页| 久久久WWW成人免费精品| 亚洲热线99精品视频| 热99RE久久精品这里都是精品免费 | 国产乱子精品免费视观看片| 又长又大又粗又硬3p免费视频| 亚洲国产91精品无码专区| 免费阿v网站在线观看g| 亚洲日产乱码一二三区别| 亚洲国产国产综合一区首页| 免费无遮挡无码永久视频| 亚洲国产成人精品无码区在线秒播 | 国产亚洲福利一区二区免费看| 国产亚洲精品免费| 亚洲乱码中文字幕综合234| 久久99毛片免费观看不卡| 麻豆69堂免费视频| 亚洲韩国—中文字幕| 伊人久久大香线蕉亚洲| 日本人的色道免费网站|