2009-12-31 104 views
15

如何將Resultset對象轉換爲JSP上的分頁視圖?ResultSet到分頁

例如,這是我的查詢結果集:

pst = con.prepareStatement("select userName, job, place from contact"); 
rs = pst.executeQuery(); 

回答

35

首先,您需要向JSP添加一個或兩個額外的請求參數:firstrow和(可選)rowcountrowcount也可以留在服務器端並完全定義。

然後一堆分頁按鈕添加到JSP:在下一個按鈕應指示Servletrowcount價值遞增的firstrow值。 以前的按鈕應明顯減少值firstrow的值爲rowcount。不要忘記處理負值並正確溢出!你可以在SELECT count(id)的幫助下完成。

然後觸發特定的SQL查詢來檢索子列表的結果。但是確切的SQL語法取決於使用的數據庫。在MySQL和PostgreSQL很容易與LIMITOFFSET條款:

private static final String SQL_SUBLIST = "SELECT id, username, job, place FROM" 
    + " contact ORDER BY id LIMIT %d OFFSET %d"; 

public List<Contact> list(int firstrow, int rowcount) { 
    String sql = String.format(SQL_SUBLIST, firstrow, rowcount); 

    // Implement JDBC. 
    return contacts; 
} 

在Oracle中你需要rownum子句的子查詢應該是這樣的:

private static final String SQL_SUBLIST = "SELECT id, username, job, place FROM" 
    + " (SELECT id, username, job, place FROM contact ORDER BY id)" 
    + " WHERE ROWNUM BETWEEN %d AND %d"; 

public List<Contact> list(int firstrow, int rowcount) { 
    String sql = String.format(SQL_SUBLIST, firstrow, firstrow + rowcount); 

    // Implement JDBC. 
    return contacts; 
} 

在DB2你需要的OLAP功能row_number()爲這個:

private static final String SQL_SUBLIST = "SELECT id, username, job, place FROM" 
    + " (SELECT row_number() OVER (ORDER BY id) AS row, id, username, job, place" 
    + " FROM contact) AS temp WHERE row BETWEEN %d AND %d"; 

public List<Contact> list(int firstrow, int rowcount) { 
    String sql = String.format(SQL_SUBLIST, firstrow, firstrow + rowcount); 

    // Implement JDBC. 
    return contacts; 
} 

我不會做MSSQL,但它在語法上類似於DB2。另見this topic

最後,只需使用JSTL c:forEach就可以通過JSP頁面呈現子列表。

<table> 
    <c:forEach items="${contacts}" var="contact"> 
     <tr> 
      <td>${contact.username}</td> 
      <td>${contact.job}</td> 
      <td>${contact.place}</td> 
     </tr> 
    </c:forEach> 
</table> 
<form action="yourservlet" method="post"> 
    <input type="hidden" name="firstrow" value="${firstrow}"> 
    <input type="hidden" name="rowcount" value="${rowcount}"> 
    <input type="submit" name="page" value="next"> 
    <input type="submit" name="page" value="previous"> 
</form> 

注意某些可能建議你需要SELECT整個表,並保存在session範圍List<Contact>和利用List#subList()進行分頁。但是,這是遠遠從數千行和多個併發用戶的內存效率。

對於對使用h:dataTable組件的JSF/MySQL上下文中的類似答案感興趣的人,您可能會發現this article有用。它還包含一些有用的與語言無關的數學,可以很好地使「類Google」分頁工作。

+0

假設用戶正在查看一個頁面時數據庫的插入和刪除操作已經發生。行號不會隨着時間的推移而穩定,我想呢?效果可能是給用戶一些意想不到的位置變化。 – djna 2009-12-31 21:53:48

+0

這是一個無關緊要的問題。您不希望查看已刪除的項目或錯過編輯的數據。唯一的解決辦法是將整個數據庫表拖入Java的內存中並且只處理它,但是你不想這樣做。 – BalusC 2009-12-31 22:00:13

+0

@BalusC - 哇。真棒回答。我可以很好地利用自己。 – ChadNC 2010-01-01 01:25:16

2

以下幾件事情可以做:

  • 馬歇爾結果設置爲對象的一些列表/記錄
  • 根據您所需的頁面大小,根據結果集計算出您將擁有多少頁面。
  • 根據要在頁面上顯示的項目數檢查所需頁面的請求參數和偏移量。因此,如果您在第4頁上顯示12,則您的偏移量爲48.
  • 根據項目數確定總頁數。

  • 顯示基於偏移,你確定你的項目(僅在項目48顯示開始)

  • 生成與頁面根據頁面,你決心總數量的分頁。

=======

這就是你的基本方法。你可以調整這個:

  • 確定的方式來限制查詢頁面(但是這不會幫助您確定頁面大小)
  • 分頁
  • 等花式方式..
+0

如果您有一個包含數千行的結果集,這不是非常有效。而不是在數據庫級別進行分頁。 – BalusC 2009-12-31 21:15:29

+0

他只需要一個起點。 – 2009-12-31 21:25:44

-1

查找值列表模式,並應用它。這通常是處理這些事情的最佳方式。

3

這個Oracle例子是錯誤的。

是的,在外部選擇whe具有良好的ROWNUM值,但它仍然是僞列,所以我們不能使用BETWEEN對它。我們需要一個更多的選擇。

正確的SQL代碼:

SELECT c.* 
    FROM (SELECT c.*, ROWNUM as rnum 
      FROM (SELECT id, username, job, place FROM contact ORDER BY id) c) c 
WHERE c.rnum BETWEEN 5 AND 10 

同志們,用堅實的SQL字符串和Statement類是SLOOOW。每次執行它時,Oracle都必須解析你的SQL。

//Slooow example 
Satement stmt = con.createStatement(); 
ResultSet rs = stmt.executeQuery("select * from my_table where id = 11"); 

使用PreparedStatement和綁定參數。

//Faster example 
    PreparedStatement ps = conn.getPrepareStatement("select * from my_table where id = ?"); 
    ps.setInt(1, 11); 

最快的解決方案是把你的sql放到oracle存儲過程中,並使用CallableStatement來調用它。

//Fastest example 
CallableStatement cs = conn.prepareCall("{? = call my_plsql_function(?)}"); 
cs.setInt(1, 11); 
-1

可以使用displaytag爲paigination或結果集但你從displattag

下載一些jar文件首先創建一個servlet的 StudentList。的java

public class StudentList extends HttpServlet 

{ 公共無效服務(HttpServletRequest的請求,響應HttpServletResponse的)拋出的ServletException,IOException異常 {

 ArrayList al=new ArrayList(); 
     StudentDao stdo=new StudentDao(); // this is DAO Class (Data Acccess Object) 

     try 
     { 
      al=stdo.getStudentList(); //getstudent list dao method 
     } 
     catch (SQLException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     request.setAttribute("al",al); 

     RequestDispatcher rd=request.getRequestDispatcher("StudentPaging.jsp"); 
     rd.forward(request,response); 

} 

}

// DAO方法

public ArrayList getStudentList() throws SQLException,Exception 
{ 
    ArrayList ai=new ArrayList(); 
    Connection con=null; 
    Statement st=null; 
    ResultSet rs=null; 
    Date dt=new Date(); 
    SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy"); 
    StudentInformation sdata=null; 

    con=MyConnection.creatConnection(); 
    if(con!=null) 
    { 
     st=con.createStatement(); 
     String select="select * from STUDENT"; 
     System.out.println(select); 

     rs=st.executeQuery(select); 
     if(rs!=null) 
     { 
      while(rs.next()) 
      { 
       sdata=new StudentInformation(); 
       sdata.setSid(rs.getString("SID")); 
       sdata.setFirstName(rs.getString("FIRSTNAME")); 
       sdata.setMiddleName(rs.getString("MIDDLENAME")); 
       sdata.setLastName(rs.getString("LASTNAME")); 
       dt=rs.getDate("SDATE"); 
       sdata.setDateofbirth(sdf.format(dt)); 
       sdata.setGender(rs.getString("GENDER")); 
       sdata.setAddress(rs.getString("ADDRESS")); 
       sdata.setHigestQulification(rs.getString("HIQULIFICATION")); 
       sdata.setLanguageKnow(rs.getString("LANGUAGE")); 
       sdata.setHobby(rs.getString("HOBBY")); 
       sdata.setTermCondition(rs.getString("TERMCON")); 
       ai.add(sdata); 
      } 
     } 
    } 
    return ai; 
} 

enter image description here