データベースへのアプリケーションクエリが多数の行を返す場合があります。フェッチされたデータはResultSet内にキャッシュされますが オブジェクト、それはしばしばそれらを扱うには大きすぎます。結果として、表示される行を制限するために、さまざまなデータセットでそれらをフィルタリングできる必要があります。この記事では、JDBC RowSetのフィルタリングの側面について詳しく説明します。 適切な例を挙げてください。
RowSetの概要
RowSet は、JDBC APIforJavaBeansコンポーネントモデルを補完するインターフェースです。これは、JDBCデータソースに接続するようにインスタンスを構成できるようにする一連のプロパティを提供します。 RowSet インスタンスは、主にデータソースからデータを取得するために使用されます。このインターフェイスのsetterメソッドは、SQLクエリのコマンドプロパティのパラメータを設定するために使用され、リレーショナルデータベースからレコードをフェッチするために使用されます。 RowSet JavaBeanコンポーネントモデルに準拠し、JavaBeanイベントをサポートします。これらのイベントは、行セットの値の変更などのイベントについて他のコンポーネントに通知するために使用されます。 RowSet インターフェイスはJDBCドライバーの上のレイヤーとして設計されており、カスタム実装が可能です。この自由により、ベンダーは独自の微調整されたエフェクトを作成し、JDBC製品と一緒に出荷することができます。
FilteredRowSet
FilteredRowSet RowSetのインターフェイス拡張です 家族。 FilteredRowSetImpl と呼ばれる、このインターフェイスのリファレンス実装があります。 クラス。 FilteredRowSetのカスタム実装を提供するため インターフェイスの場合、 FilteredRowSetImplを拡張できます。 クラスを作成するか、 FilteredRowSetを使用します 要件に応じたインターフェース。場合によっては、 RowSetのコンテンツに何らかの形式のフィルタリングを適用する必要があります。 フェッチします。考えられる簡単な解決策は、すべての RowSetにクエリ言語を提供することです。 実装。ただし、 RowSet であるため、これは実行可能なアプローチではありません。 切断された軽量コンポーネントのアイデアで構築されています。これにより、オブジェクトが重くなり、その設計原則に反することになります。ニーズに対応するアプローチが必要ですが、フィルタリングの処理ロジックとともに重いクエリ言語を注入することはありません。 JDBC FilteredRowSet 標準実装はRowSetを拡張します CachedRowSetなどのサブインターフェイスを介して およびWebRowSet それぞれ。 FilteredRowSet CachedRowSetによって提供される保護されたカーソル操作メソッドのセットを介してカーソルを操作できます インターフェース。これらのメソッドは、要件に応じてオーバーライドでき、 RowSetのフィルタリング中に役立ちます。 コンテンツ。
簡単な例
これは、 FilteredRowSetがどのように行われるかを示す例です。 データベースに対して実行されたクエリによって返されるコンテンツを格納するために使用されます。クエリの結果は、 FilteredRowsetに適用された構成に従ってフィルタリングされます 実装。これは、クエリによって返された結果から関心のある表示コンテンツまたは行を定義します。次の例では、 SimpleFilterというフィルタークラスを作成しました。 。このクラスは、この場合、 FilteredRowSetのカスタム実装を定義します。 。次に、データベースクエリから返された結果にこのフィルターを適用しました。 フィルタリング 表示される行数を制限することを意味します。したがって、ここでは、提供された選択した著者名に応じて、書籍情報レコードの数を制限します。
実践的には、次のJavaコードで使用されるデータベーステーブルを以下に示します。
図1: データベーステーブル、本
図2: データベーステーブル、作成者
図3: データベーステーブル、 book_author
SimpleFilter クラスは述語を実装します のは、カスタムフィルターを実装するためのメソッドを評価します。
package org.mano.example;
import javax.sql.RowSet;
import javax.sql.rowset.Predicate;
import java.sql.SQLException;
public class SimpleFilter implements Predicate {
private String[] authors;
private String colname = null;
private int colno = -1;
public SimpleFilter(String[] authors, String colname) {
this.authors = authors;
this.colno = -1;
this.colname = colname;
}
public SimpleFilter(String[] authors, int colno) {
this.authors = authors;
this.colno = colno;
this.colname = null;
}
@Override
public Boolean evaluate(Object value, String colName) {
if (colName.equalsIgnoreCase(this.colname)) {
for (String author : this.authors) {
if (author.equalsIgnoreCase((String)value)) {
return true;
}
}
}
return false;
}
@Override
public Boolean evaluate(Object value, int colNumber) {
if (colNumber == this.colno) {
for (String author : this.authors)
if (author.equalsIgnoreCase((String)value)) {
return true;
}
}
}
return false
}
@Override
public Boolean evaluate(RowSet rs) {
if (rs == null) return false;
try {
for (int i=0;i<authors.length;i++) {
String al = null;
if (this.colno> 0) {
al = (String)rs.getObject(this.colno);
} else if (this.colname != null) {
al = (String)rs.getObject(this.colname);
} else {
return false;
}
if (al.equalsIgnoreCase(authors[i])) {
return true;
}
}
} catch (SQLException e) {
return false;
}
return false;
}
}
このクラスは、 SimpleRowSetを実行するために使用されます フィルタクラス。 FilteredRowSetをどのように利用したかに注意してください アプリケーションでデータをフィルタリングします。処理は、SQLデータベースレベルではなく、アプリケーションレベルで行われます。その結果、一連のフィルターを実装し、それらを同じ結果セットに適用して、目的の結果を得ることができます。変更された結果を取得するためにデータベースに対して複数のクエリを実行する必要がないため、これはパフォーマンスを活用します。代わりに、データベースに対して1回実行されたクエリ結果に複数のフィルタリングを適用できます。アプリケーションには2つの重要なフェーズがあります。
- データをフィルタリングするための基準を定めるフィルターを作成します。これは、述語を実装することによって行われます。 インターフェース。異なる引数のセットを受け入れる複数のコンストラクターが存在する可能性があります。また、フィルターには Evaluation()の配列が含まれている場合があります。 メソッドは、独自の実装セットを持つさまざまな引数セットも受け入れます。
- FilteredRowSet 目的の効果を得るには、クラスをインスタンス化する必要があります。これは、ここで applyFilter()を使用して行いました。 方法。 FilteredRowSet 提供されたカスタムフィルタークラスを使用して、表示するレコードを決定します。
package org.mano.example;
import com.sun.rowset.FilteredRowSetImpl;
import javax.sql.RowSet;
import javax.sql.rowset.FilteredRowSet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DemoApp {
private static final String DB_URL =
"jdbc:mysql://localhost:3306/my_lib";
private static final String DB_DRIVER =
"com.mysql.cj.jdbc.Driver";
private static final String DB_USERNAME =
"root";
private static final String DB_PASSWORD =
"secret";
public static Connection conn = null;
public static FilteredRowSet filteredRowSet = null;
public static void main(String[] args) {
try {
Class.forName(DB_DRIVER);
conn = DriverManager.getConnection(DB_URL,
DB_USERNAME,DB_PASSWORD);
System.out.println("Database connection
successful.");
applyFilter();
} catch (SQLException | ClassNotFoundException ex) {
System.out.println(ex);
} finally {
if (conn != null) {
try {
conn.close();
catch (SQLException ex) {
ex.printStackTrace();
}
}
if (filteredRowSet != null) {
try {
filteredRowSet.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
public static void applyFilter() {
String[] arr = {"Donne", "Milton"};
SimpleFilter aFilter = new SimpleFilter(arr, 3);
try {
filteredRowSet = new FilteredRowSetImpl();
filteredRowSet.setCommand("SELECT title, f_name, l_name "
+ "FROM book_author BA, "
+ "author A, "
+ "book B "
+ "WHERE A.auth_id = BA.fk_author "
+ "AND B.book_id = BA.fk_book");
filteredRowSet.execute(conn);
System.out.println
("--------------------------------------------");
System.out.println("Before applying any
filter:");
System.out.println
("--------------------------------------------");
show(filteredRowSet);
System.out.println
("--------------------------------------------");
System.out.println("After applying
filter :");
System.out.println
("--------------------------------------------");
filteredRowSet.beforeFirst();
filteredRowSet.setFilter(aFilter);
show(filteredRowSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void show(RowSet rs) {
try {
while (rs.next()) {
System.out.println(rs.getString(1) + " / "
+ rs.getString(2)
+ " "+rs.getString(3));
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
出力
Database connection successful. -------------------------------------------- Before applying any filter: -------------------------------------------- Gulliver's Travels / Jonathan Swift ... Ill Pensoroso / John Milton Areopagitica / John Milton -------------------------------------------- After applying filter: -------------------------------------------- The Flea / John Donne Holy Sonnet / John Donne Paradise Lost / John Milton Paradise Regained / John Milton Ill Pensoroso / John Milton Areopagitica / John Milton
結論
クエリから返された多数の行を操作するには、多くの問題があります。 1つは、取得したデータがメモリを占有することです。
必要性と関連性に応じてそれらを制限することは常に役立ちます。 RowSetを使用 、追加のデータベースリクエストを行うことなく、基準に従ってそれらをフィルタリングできます。これにより、データベース行の操作がより管理しやすくなり、コードの効率が向上します。