ページングの問題は、ほとんどすべての開発者が遭遇する非常に一般的な問題です。ここではページングの具体的な方法については説明しませんが、Web モードでのページングの原理について説明します。 1 つ目は、結果セット (データベースへのクエリから得られた結果として表示) を取得するためのクエリです。結果が多数ある場合、通常はすべてのデータを一度に表示せず、ページングを使用して特定のデータ (たとえば、 20項目として)。 HTTP のステートレスな性質により、各送信は新しいリクエストとして扱われ、ページが変更された場合でも、最後の結果は次のリクエストに影響を与えません。
他にあるかどうかはわかりませんが、ページングを実装する 3 つの方法を次に示します。
1. クエリ結果のデータを毎回すべて取得し、指定したレコードをページ番号に従って表示します。
2. ページに基づいてデータを 1 ページだけ取得し、このページを表示します。ここで SQL ステートメントを構築する必要があります。
3. 特定のページ数のデータを取得することは、前の 2 つの間の妥協案です。
ここで注意すべき点は、データがリクエストに配置されるかセッションに配置されるかということです。これについては、ここで 1 つずつ説明します。
1. 大量のメモリを占有するため、通常はセッションには配置されないため、リクエストに配置する必要があります。
利点: 実装は比較的単純で、クエリ速度は比較的高速です。
短所: より多くのメモリを消費し、ネットワーク上で大量のデータを送信します。
この方法は、比較的少量のデータを含むクエリに適しています。ここでは、ページを変更するときに再クエリする必要がないようにデータをセッションに配置する人もいますが、これは非常に悪いことであり、この方法で使用しないことを強くお勧めします。
2. セッションに入れても意味がないため、セッションには絶対に入れられません。
利点: メモリの使用量が少なくなります。
欠点: ページ数を知るためにはレコード数を知る必要があるため、最初にクエリ結果の総数を取得する必要があります。さらに、データベースごとに異なるページング クエリ ステートメントを作成する必要があります。
3. この状況はセッション内に配置する必要があります。そうでない場合、なぜ複数のページをフェッチするのでしょうか? この実装は、たとえば、レコード 1 から 10 までを保存する場合、ページを変更するときの数を減らすためです。 10 はセッションから直接取得できます。ページ 11 に変更すると、キャッシュを 11 にリセットできます。
20 ページのデータ (または 5 ~ 15 ページのデータ)。この場合、10 回の変更に対して必要なデータベース クエリ操作は 1 回だけです。
利点: 使用するメモリが比較的少なく、平均クエリ速度が向上します。
欠点: 実装がより複雑で、ダーティ データが存在する可能性があり、キャッシュ コレクションを自分で定義する必要があります。クエリされるデータの量が比較的大きい場合は、この方法の使用を検討できます。
次の設計では、毎回 1 ページのデータのみを取得し、クエリの合計数を毎回リセットする必要があります。これは比較的一般的なページングの実装です。
ここでインターフェースを設計します。
packagetreeroot.util;import java.util.List;/*** このインターフェースは、ページング機能を実装するために使用されます。ここでは変更機能が提供されていないことに注意してください。 * @authortreerot* @version 1.0* @since 2004-9-30*/publicinterface Pageable{ /** * データ結果の取得* @return */ public List getResult(); /** * クエリの総数を取得* @return */ public int getCount(); /** * ページごとのレコード数を取得します* @return */ public int getPageSize(); /** * 現在のページ番号を取得します* @return */ public int getCurrentPage(); /** * 合計ページ数を取得します* @return */ public int getPages(); /** * 各ページに表示されるデフォルトのレコード数*/ publicfinal static int DEFAULT_PAGESIZE=20;}このインターフェイスは非常にシンプルで、結果リストとページングに必要な情報がいくつか含まれています。
1. このインターフェイスの実装は、特定のクエリ内の特定のデータ ページを表します。これは、最後のクエリとは何の関係もありません。
2. このインターフェイスの実装は読み取り専用である必要があります。これは、変更できないことを意味します。
3. getPages() メソッドは冗長ですが、このメソッドはここでも提供されています。
抽象的な実装を以下に示します。
packagetreeroot.util;import java.util.List;/*** @authortreerot* @version 1.0* @since 2004-9-30*/public abstract class AbstractPageimplements Pageable{ private int currentPage;ページ; protected int count; protected List result; /** * 現在のページを指定します* @param currentPage * @throws PageException */ public AbstractPage(int currentPage){ this(currentPage,Pageable.DEFAULT_PAGESIZE); } /** * 現在のページとページ サイズを指定します* @param currentPage * @param pageSize * @throws PageException */ public AbstractPage(int currentPage,int pageSize) { this.currentPage=currentPage ; this.pageSize=pageSize; } protected void checkPage(int currentPage) throws PageException{ if((currentPage<1)||(currentPage>this.getPages())) throw new PageException("ページが範囲外です: 総ページ数は "+this.getPages()+"、現在のページは " +currentPage); } /** * このメソッドは初期化、つまりカウント値と結果を計算するためにサブクラスによってオーバーライドされ、サブクラスのコンストラクターで呼び出されます。 */ abstract protected void init() throws PageException; public List getResult() { return result; } public int getPageSize() { return currentPage; public int getPages() { if(pages==0) this.pages=(count+pageSize-1)/pageSize return;ページ; }}この抽象クラスはインターフェイス内のすべてのメソッドを実装しますが、抽象メソッド init() を定義します。これはサブクラスで実装する必要があります。上記のインターフェイスと抽象クラスは比較的単純に見えますが、実際には実装に関しては何もしていませんが、開発に大きな助けとなります。この抽象クラスは必要に応じて継承でき、データはさまざまな方法 (リストを通じて直接、または JDBC、Hibernate などを通じて取得できます) で取得できますが、結果をリストにカプセル化する必要があります。 Hibernate経由は特に便利そうです。
PageException はカスタム例外です
packagetreeroot.util /*** @author Treeroot* @version 1.0* @since 2004-9-30*/public class PageException extends Exception{ public PageException(){ super() } public PageException(String message){ super(メッセージ); }}