web-dev-qa-db-ja.com

ResultSetをページネーションに設定

ResultsetオブジェクトをJSPのページ付けされたビューに変換するにはどうすればよいですか?

たとえば、これは私のクエリと結果セットです。

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

開始するには、JSPに1つまたは2つの追加のリクエストパラメータを追加する必要があります:firstrowおよび(オプションで)rowcountrowcountは省略して、サーバー側で完全に定義することもできます。

次に、一連のページングボタンをJSPに追加します。nextボタンは、Servletの値を次の値でインクリメントするようにfirstrowに指示する必要があります。 rowcountpreviousボタンは、明らかにfirstrowの値をrowcountの値でデクリメントする必要があります。負の値とオーバーフローを正しく処理することを忘れないでください!あなたはSELECT count(id)の助けを借りてそれを行うことができます。

次に、特定のSQLクエリを実行して、結果のサブリストを取得します。ただし、正確なSQL構文は、使用するDBによって異なります。 MySQLとPostgreSQLでは、LIMIT句とOFFSET句を使用すると簡単です。

_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 function 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に似ています。 このトピック も参照してください。

最後に、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>
_

一部のmayは、テーブル全体をSELECTし、セッションスコープに_List<Contact>_を保存して、 を利用する必要があることを示唆していることに注意してください。 List#subList() ページ付けします。しかし、これは遠い数千の行と複数の同時ユーザーによるメモリ効率です。

_h:dataTable_コンポーネントを使用したJSF/MySQLコンテキストでの同様の回答に関心がある場合は、 この記事 が役立つ場合があります。また、「Googleのような」ページ付けをうまく機能させるための、言語に依存しない便利な数学も含まれています。

39
BalusC

このOracleの例は間違っています。

はい、外側の選択では、適切なROWNUM値がありますが、それでも疑似列であるため、BETWEENを使用することはできません。もう1つ選択する必要があります。

正しい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を実行するたびに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);
3
Vasily Komarov

これがあなたができるいくつかのことです:

  • 結果セットをオブジェクト/レコードのリストにマーシャルします
  • 必要なページサイズに基づいて、結果セットに基づいてページ数を計算します。
  • 必要なページのリクエストパラメータと、ページに表示するアイテムの数に基づいたオフセットを確認してください。したがって、4ページに12が表示されている場合、オフセットは48です。
  • アイテムの数に基づいて、ページの総数を決定します。

  • 決定したオフセットに基づいてアイテムを表示します(アイテム48からのみ表示)

  • 決定した総ページ数に基づいて、ページ数を使用してページ付けを生成します。

=======

それがあなたの基本的なアプローチです。あなたはこれを微調整することができます:

  • クエリをページに制限する方法を決定する(ただし、これはページサイズの決定には役立ちません)
  • ページネーションの派手な方法
  • 等..
2
Shaun F