18 JDBC RowSet
この章の構成は、次のとおりです。
18.1 JDBC RowSetの概要
RowSetは、Java Database Connectivity(JDBC)の結果セットまたは表形式データソースの一連の行をカプセル化するオブジェクトです。RowSetは、JavaBeansなどのコンポーネント・ベースの開発モデル、一連の標準プロパティおよびイベント通知メカニズムをサポートしています。
RowSetsは、JDBC 2.0で、オプションのパッケージによって導入されました。ただし、RowSetsの実装はJDBC RowSet Implementations Specification(JSR-114)で標準化され、Java Platform, Standard Edition(Java SE)5.0以降、オプションでないパッケージとして利用できます。Java SE 6.0 RowSetsには、RowIdや各国語文字セットなどのような機能をサポートするAPIがより多く含まれます。Java SE Javadocには、JDBC RowSetの実装のための、標準インタフェースと基本クラスに関する情報が含まれています。
JSR-114仕様には、次の5種類のRowSetの実装詳細が記載されています。
-
CachedRowSet
-
JdbcRowSet
-
WebRowSet
-
FilteredRowSet
-
JoinRowSet
Oracle JDBCは、5種類のRowSetすべてを、oracle.jdbc.rowset
パッケージにあるインタフェースおよびクラスを介してサポートしています。Oracle Database 11gリリース1以降、サーバー側ドライバにRowSetsサポートが追加されました。このため、Oracle Database 11gリリース1からは、すべてのOracle JDBCドライバの型にわたり、RowSetサポートは均一です。標準のOracle JDBC Java Archive(JAR)ファイル、たとえば、ojdbc6.jar
およびojdbc7.jar
にはoracle.jdbc.rowset
パッケージが含まれます。
ノート:
-
接尾辞名の異なる他のJARファイル、たとえば、
ojdbc6_g.jar
およびojdbc6dms.jar
にも、oracle.jdbc.rowset
パッケージが含まれます。 -
Oracle Database 10gリリース2では、実装クラスは
ojdbc14.jar
ファイルにパッケージ化されていました。 -
Oracle Database 10gリリース2より前では、実装クラスは
ojdbc12.jar
ファイルにパッケージ化されていました。 -
Oracle Database 11gリリース1より前は、RowSetsサポートはサーバー側ドライバでは利用できませんでした。
ノート:
Oracle Database 10gリリース2 (10.2)では、このパッケージは標準Oracle JDBC JARファイル(classes12.jar
、ojdbc5.jar
およびojdbc6.jar
)に含まれています。Oracle Database 10gリリース2 (10.2)より前では、row set実装クラスはocrs12.jar
ファイルにパッケージ化されていました。
Oracle RowSet実装を使用するには、必要なRowSet型のパッケージからoracle.jdbc.rowset
パッケージ全体、または特定のクラスおよびインタフェースをインポートする必要があります。またクライアント側では、CLASSPATH
環境変数にojdbc6.jar
またはojdbc7.jar
などのOracle JARファイルをインクルードする必要があります。
この項の内容は次のとおりです。
18.1.1 RowSetのプロパティ
javax.sql.RowSet
インタフェースは、単一のインタフェースでデータソースのデータにアクセスするために変更できるJavaBeansプロパティ一式を提供します。プロパティには、たとえば接続文字列、ユーザー名、パスワード、接続の種類および問合せ文字列があります。
関連項目:
プロパティおよびプロパティの説明の完全なリストは、http://docs.oracle.com/javase/1.5.0/docs/api/javax/sql/RowSet.html
のJava2 Platform, Standard Edition (J2SE)のJavadocを参照
このインタフェースは、プロパティ値の設定および取出しに必要な標準アクセッサ・メソッドを提供します。次のコードは、一部のRowSet
プロパティを設定します。
... rowset.setUrl("jdbc:oracle:oci:@"); rowset.setUsername("HR"); rowset.setPassword("hr"); rowset.setCommand("SELECT employee_id, first_name, last_name, salary FROM employees"); ...
この例では、URL、ユーザー名、パスワードおよびSQL問合せが、従業員番号、従業員名および全従業員の給与をRowSet
オブジェクト内に取り出すためのRowSet
プロパティとして設定されています。
18.1.2 イベントおよびイベント・リスナー
RowSetはJavaBeansイベントをサポートします。RowSet
インタフェースは、次のタイプのイベントをサポートします。
-
cursorMoved
このイベントはカーソルが移動するたびに生成されます。たとえば、
next
メソッドまたはprevious
メソッドがコールされると生成されます。 -
rowChanged
このイベントは、RowSetに行が挿入されるか、RowSetの行が更新されるか、またはRowSetから行が削除されると生成されます。
-
rowSetChanged
このイベントは、RowSet全体が作成または変更されると生成されます。たとえば、
execute
メソッドがコールされると生成されます。
アプリケーション・コンポーネントでは、RowSetリスナーを実装し、これらのRowSetイベントをリスニングして、イベントの発生時に必要な操作を実行できます。これらのイベントに関係のあるアプリケーション・コンポーネントの場合は、標準のjavax.sql.RowSetListener
インタフェースを実装し、RowSet
オブジェクトにこれらのリスナー・オブジェクトを登録する必要があります。リスナーの登録にはRowSet.addRowSetListener
メソッドを使用し、登録を解除するにはRowSet.removeRowSetListener
メソッドを使用します。複数のリスナーを同じRowSet
オブジェクトに登録できます。
次のコードは、RowSetリスナーを登録します。
... MyRowSetListener rowsetListener = new MyRowSetListener (); // adding a rowset listener rowset.addRowSetListener (rowsetListener); ...
次のコードは、リスナーを実装します。
public class MyRowSetListener implements RowSetListener { public void cursorMoved(RowSetEvent event) { // action on cursor movement } public void rowChanged(RowSetEvent event) { // action on change of row } public void rowSetChanged(RowSetEvent event) { // action on changing of rowset } }// end of class MyRowSetListener
選択されたイベントのみを処理するアプリケーションの場合、すべてのイベント処理メソッド用の空の実装を持つ抽象クラスであるoracle.jdbc.rowset.OracleRowSetListenerAdapter
クラスを使用することにより、必要なイベント処理メソッドのみを実装することができます。次のコードでは、rowSetChanged
イベントのみが処理され、残りのイベントは処理されません。
... rowset.addRowSetListener(new oracle.jdbc.rowset.OracleRowSetListenerAdapter () { public void rowSetChanged(RowSetEvent event) { // your action for rowSetChanged } } ); ...
18.1.3 コマンド・パラメータおよびコマンド実行
RowSet
オブジェクトのcommand
プロパティは、通常はSQL問合せ文字列を表し、処理時に実際のデータをRowSet
オブジェクトに移入します。通常のJDBC処理と同様に、この問合せ文字列は入力やバインド・パラメータをとることができます。javax.sql.RowSet
インタフェースにも、このSQL問合せに入力パラメータを設定するメソッドがあります。必要な入力パラメータが設定された後でSQL問合せが処理され、基礎となるデータソースのデータをRowSet
オブジェクトに移入できます。次のコードは、この単純な手順を示しています。
... rowset.setCommand("SELECT first_name, last_name, salary FROM employees WHERE employee_id = ?"); // setting the employee number input parameter for employee named "Douglas" rowset.setInt(1, 199); rowset.execute(); ...
前述の例では、従業員番号199が、RowSet
オブジェクトのcommand
プロパティで指定されたSQL問合せの入力パラメータまたはバインド・パラメータとして設定されています。SQL問合せが処理されると、RowSet
オブジェクトは、従業員番号199の従業員の従業員名と給与情報で満たされます。
18.1.4 RowSetの横断について
javax.sql.RowSet
インタフェースは、java.sql.ResultSet
インタフェースを拡張します。そのため、RowSet
インタフェースでは、カーソル移動および位置指定の各メソッドがResultSet
インタフェースから継承され、RowSet
オブジェクト内のデータの横断に使用されます。継承されるメソッドの中には、absolute
、beforeFirst
、afterLast
、next
およびprevious
があります。
RowSet
インタフェースは、データを取得および更新するためのResultSet
インタフェースと同じように使用できます。RowSet
インタフェースでは、オプションでスクロール可能および更新可能な結果セットを実装できます。ResultSet
インタフェースに含まれるすべてのフィールドおよびメソッドが、RowSet
に実装されます。
ノート:
java.sql.ResultSet
インタフェースのスクロール可能で更新可能なプロパティは、ResultSet
のOracle実装でも提供されます。
次のコードは、RowSetをスクロールする方法を示します。
/** * Scrolling forward, and printing the empno in * the order in which it was fetched. */ ... rowset.setCommand("SELECT empno, ename, sal FROM emp"); rowset.execute(); ... // going to the first row of the rowset rowset.beforeFirst (); while (rowset.next ()) System.out.println ("empno: " +rowset.getInt (1));
前述のコードでは、beforeFirst
メソッドによって、カーソル位置がRowSetの最初の行の前に初期化されます。行は、next
メソッドを使用して前方方向に取り出されます。
次のコードは、RowSetを逆方向にスクロールする方法を示します。
/** * Scrolling backward, and printing the empno in * the reverse order as it was fetched. */ //going to the last row of the rowset rowset.afterLast (); while (rowset.previous ()) System.out.println ("empno: " +rowset.getInt (1));
前述の例では、RowSet
の最後の行の後にカーソル位置が初期化されます。行は、RowSet
のprevious
メソッドを使用して逆方向に取り出されます。
行の挿入、更新および削除は、結果セット機能と同様に行セット機能でもサポートされます。行セットを更新可能にするには、setReadOnly(false)
およびacceptChanges
の各メソッドをコールする必要があります。
次のコードは、行セットの5番目の位置に1行を挿入します。
... /** * Make rowset updatable */ rowset.setReadOnly (false); /** * Inserting a row in the 5th position of the rowset. */ // moving the cursor to the 5th position in the rowset if (rowset.absolute(5)) { rowset.moveToInsertRow (); rowset.updateInt (1, 193); rowset.updateString (2, "Smith"); rowset.updateInt (3, 7200); // inserting a row in the rowset rowset.insertRow (); // Synchronizing the data in RowSet with that in the database. rowset.acceptChanges (); } ...
前述の例では、パラメータ5
が指定されたabsolute
メソッドをコールすることにより、RowSetの5番目の位置にカーソルが移動し、moveToInsertRow
メソッドをコールすることにより、RowSetに新しい行を挿入するための場所が作成されます。新しく作成された行を更新するには、update
XXX
メソッドを使用します。行のすべての列が更新されると、insertRow
がコールされ、そのRowSetが更新されます。変更はacceptChanges
メソッドを使用してコミットします。
18.2 CachedRowSetについて
CachedRowSetは、行がキャッシュされ、切断されている(つまり、データベースとのアクティブ接続を持たない)RowSetです。oracle.jdbc.rowset.OracleCachedRowSet
クラスは、CachedRowSetのOracle実装です。これは標準のリファレンス実装と相互運用できます。ojdbc6.jar
ファイルおよびojdbc7.jar
ファイルのOracleCachedRowSet
クラスは、標準のJSR-114インタフェースjavax.sql.rowset.CachedRowSet
を実装します。
次のコードでは、OracleCachedRowSet
オブジェクトを作成し、プロパティとしてRowSet
オブジェクトの接続URL、ユーザー名、パスワードおよびSQL問合せを設定します。RowSet
オブジェクトには、execute
メソッドを使用してデータが移入されます。execute
メソッドを処理した後、java.sql.ResultSet
オブジェクトとしてRowSet
オブジェクトを使用できるため、データの取得、スクロール、挿入、削除または更新を実行できます。
... RowSet rowset = new OracleCachedRowSet(); rowset.setUrl("jdbc:oracle:oci:@"); rowset.setUsername("HR"); rowset.setPassword("hr"); rowset.setCommand("SELECT employee_id, first_name, last_name, salary FROM employees"); rowset.execute(); while (rowset.next ()) { System.out.println("employee_id: " +rowset.getInt (1)); System.out.println("first_name: " +rowset.getString (2)); System.out.println("last_name: " +rowset.getString (3)); System.out.println("sal: " +rowset.getInt (4)); } ...
問合せによりCachedRowSet
オブジェクトにデータを移入するには、次のステップを実行します。
-
OracleCachedRowSet
をインスタンス化します。 -
Url
(接続URL)、Username
、Password
およびCommand
(問合せ文字列で、RowSet
オブジェクトのプロパティ)を設定します。接続型を設定することもできますが、それはオプションです。 -
execute
メソッドをコールして、CachedRowSet
オブジェクトにデータを移入します。execute
のコールにより、問合せセットがこのRowSetのプロパティとして実行されます。
OracleCachedRowSet rowset = new OracleCachedRowSet (); rowset.setUrl ("jdbc:oracle:oci:@"); rowset.setUsername ("HR"); rowset.setPassword ("hr"); rowset.setCommand ("SELECT employee_id, first_name, last_name, salary FROM employees"); rowset.execute ();
populate
メソッドを使用して、CachedRowSet
オブジェクトに既存のResultSet
オブジェクトを移入できます。これを行うには、次のステップを完了します。
-
OracleCachedRowSet
をインスタンス化します。 -
すでに使用可能な
ResultSet
オブジェクトをpopulate
メソッドに渡して、RowSet
オブジェクトにデータを移入します。
// Executing a query to get the ResultSet object. ResultSet rset = pstmt.executeQuery (); OracleCachedRowSet rowset = new OracleCachedRowSet (); // the obtained ResultSet object is passed to the populate method // to populate the data in the rowset object. rowset.populate (rset);
前述の例では、問合せを実行してResultSet
オブジェクトを取得し、そのResultSet
オブジェクトがCachedRowSet
オブジェクトのpopulate
メソッドに渡されて、結果セットの内容がCachedRowSetに移入されています。
ノート:
既存のResultSet
オブジェクトをCachedRowSet
オブジェクトへのデータの移入に使用する場合には、プロパティが適用される接続または結果セットがすでに作成されているため、トランザクションの分離や結果セットの同時実行性モードなどの接続プロパティおよびバインド・プロパティを設定することはできません。
次のコードは、OracleCachedRowSet
オブジェクトをファイルに対してシリアライズしてから取得します。
// writing the serialized OracleCachedRowSet object { FileOutputStream fileOutputStream = new FileOutputStream("emp_tab.dmp"); ObjectOutputStream ostream = new ObjectOutputStream(fileOutputStream); ostream.writeObject(rowset); ostream.close(); fileOutputStream.close(); } // reading the serialized OracleCachedRowSet object { FileInputStream fileInputStream = new FileInputStream("emp_tab.dmp"); ObjectInputStream istream = new ObjectInputStream(fileInputStream); RowSet rowset1 = (RowSet) istream.readObject(); istream.close(); fileInputStream.close(); }
前述のコードでは、emp_tab.dmp
ファイル用にFileOutputStream
オブジェクトがオープンされ、データを移入されたOracleCachedRowSet
オブジェクトがObjectOutputStream
を使用してこのファイルに書き込まれます。シリアライズされたOracleCachedRowSet
オブジェクトは、FileInputStream
およびObjectInputStream
オブジェクトを使用して取り出されます。
InputStream
、OutputStream
、バイナリ・ラージ・オブジェクト(BLOB)およびキャラクタ・ラージ・オブジェクト(CLOB)などの非シリアライズ形式のデータは、OracleCachedRowSet
によってシリアライズされます。また、OracleCachedRowSets
は独自のメタデータを実装するため、追加のラウンドトリップを必要とせずに取得できます。次のコードは、RowSetのメタデータを取得する方法を示します。
... ResultSetMetaData metaData = rowset.getMetaData(); int maxCol = metaData.getColumnCount(); for (int i = 1; i <= maxCol; ++i) System.out.println("Column (" + i +") " + metaData.getColumnName(i)); ...
OracleCachedRowSet
クラスはシリアライズ可能なので、Remote Method Invocation(RMI)の場合と同様に、ネットワークや別のJava仮想マシン(JVM)の間で渡すことができます。OracleCachedRowSet
クラスにデータが移入されると、任意のJVMまたはJDBCドライバを使用していない環境での移動が可能になります。RowSetにデータをコミットするには、JDBCドライバがインストールされている必要があります。
データを取得して、OracleCachedRowSet
クラスでそれにデータを移入する処理の全体はサーバーで実行され、データを移入されたRowSetは、RMIやEnterprise Java Beans(EJB)などの適切なアーキテクチャを使用してクライアントに渡されます。クライアントは、取得、スクロール、挿入、更新および削除などすべての操作を、RowSet上で、データベースに接続しないで実行できます。データベースにデータがコミットされる場合は常に、RowSet内のデータとデータベース内のデータを同期させるacceptChanges
メソッドがコールされます。このメソッドはJDBCドライバを利用するため、JVM環境にJDBC実装が含まれる必要があります。このアーキテクチャは、携帯情報端末(PDA)などのThinクライアントが関係するシステムに適しています。
CachedRowSet
オブジェクトにデータを移入すると、このオブジェクトをResultSet
オブジェクト、またはRMIやその他の適切なアーキテクチャを使用してネットワークを通じて渡すことが可能な他のオブジェクトとして使用できます。
CachedRowSetには、この他に次のような主要機能があります。
-
RowSetのクローニング
-
RowSetのコピーの作成
-
RowSetの共有コピーの作成
CachedRowSetの制約事項
OracleCachedRowSet
はシリアライズ可能なので、更新可能な結果セットに適用される、シリアライズ以外のすべての制約をここで適用できます。SQL問合せには、次の制約があります。
-
データベース内の1つの表のみを参照できます。
-
結合操作は含まれません。
-
参照先の表の主キーを選択します。
また、新しい行を挿入するには、SQL問合せが次の条件を満たしている必要があります。
-
基礎となる表のNULL化可能でない列すべてを選択します。
-
デフォルト値のないすべての列を選択します。
ノート:
データはすべてメモリーにキャッシュされるため、
CachedRowSet
には大量のデータを格納できません。したがって、大量のデータを戻す可能性のあるOracleCachedRowSet
を問合せで使用しないことをお薦めします。
結果セットのトランザクションの分離や同時実行性モードなど接続プロパティは、RowSetへのデータの移入後には設定できません。このプロパティは、データを取り出した後には接続に適用できないためです。
18.3 JdbcRowSetについて
JdbcRowSetは、ResultSet
オブジェクトをラップするRowSetです。これは、接続RowSetであり、JavaBeanインタフェース形式のJDBCインタフェースを提供します。JdbcRowSetのOracle実装は、oracle.jdbc.rowset.OracleJDBCRowSet
です。ojdbc6.jar
ファイルおよびojdbc7.jar
ファイルのOracleJDBCRowSet
クラスは、標準のJSR-114インタフェースjavax.sql.rowset.JdbcRowSet
を実装します。
表18-1は、JdbcRowSet
インタフェースとCachedRowSet
インタフェースの違いを示しています。
表18-1 JDBCのRowSetとCachedRowSetの比較
RowSetのタイプ | シリアライズ可能 | データベースへの接続 | JVM内での移動が可能 | データベースに対するデータの同期化 | JDBCドライバの存在 |
---|---|---|---|---|---|
JDBC |
あり |
あり |
なし |
なし |
あり |
キャッシュ |
あり |
なし |
あり |
あり |
なし |
JdbcRowSetは接続されているRowSetで、データベースへのライブ接続を持ち、JdbcRowSet上のすべてのコールは、JDBC接続、文または結果セットのマッピング・コールに反映されます。CachedRowSetは、開いているデータベースへの接続をいっさい持ちません。
JdbcRowSetではJDBCドライバが存在する必要があるのに対して、CachedRowSetの場合は、操作時にJDBCドライバが存在する必要はありません。ただし、JdbcRowSetおよびCachedRowSetでは、RowSetへのデータ移入時とRowSetの変更をコミットするときには、JDBCドライバが必要です。
次のコードは、JdbcRowSetの使用方法を示します。
... RowSet rowset = new OracleJDBCRowSet(); rowset.setUrl("java:oracle:oci:@"); rowset.setUsername("HR"); rowset.setPassword("hr"); rowset.setCommand("SELECT empno, ename, sal FROM emp"); rowset.execute(); while (rowset.next()) { System.out.println("empno: " + rowset.getInt(1)); System.out.println("ename: " + rowset.getString(2)); System.out.println("sal: " + rowset.getInt(3)); } ...
前述の例では、接続URL、ユーザー名、パスワードおよびSQL問合せがRowSet
オブジェクトのプロパティとして設定され、SQL問合せがexecute
メソッドを使用して処理され、行がRowSet
オブジェクトに移入されたデータを横断して取得され出力されます。
18.4 WebRowSetについて
WebRowSetは、CachedRowSetの拡張機能です。このRowSetは一連のフェッチされる行または表データを表し、データソースとのアクティブな接続を保持せずに、各層およびコンポーネント間で渡すことができます。WebRowSet
インタフェースは、結果セットの生成と使用をサポートし、結果セットとデータソースとの同期をExtensible Markup Language(XML)形式および接続切断方式の両方でサポートします。これにより、層と層をまたがり、またインターネット・プロトコルを介して、結果セットを移送できます。
WebRowSetのOracle実装は、oracle.jdbc.rowset.OracleWebRowSet
です。このクラスは、ojdbc6.jar
ファイルおよびojdbc7.jar
ファイル内にあり、標準のJSR-114インタフェースjavax.sql.rowset.WebRowSet
を実装します。このクラスは、oracle.jdbc.rowset.OracleCachedRowSet
クラスも拡張します。OracleWebRowSet
クラスは、OracleCachedRowSet
クラスで使用可能なメソッドの他に、次のメソッドも提供します。
public OracleWebRowSet() throws SQLException
これは、
OracleWebRowSet
オブジェクトの作成に使用するコンストラクタであり、OracleCachedRowSet
オブジェクトのデフォルト値、デフォルトのOracleWebRowSetXmlReader
およびデフォルトのOracleWebRowSetXmlWriter
によって初期化されます。public void writeXml(java.io.Writer writer) throws SQLException public void writeXml(java.io.OutputStream ostream) throws SQLException
これらのメソッドは、
OracleWebRowSet
オブジェクトを、提供されたWriter
またはOutputStream
オブジェクトにJSR-114 XMLスキーマ準拠のXML形式で書き込みます。RowSetデータの他に、RowSetのプロパティとメタデータも書き込まれます。public void writeXml(ResultSet rset, java.io.Writer writer) throws SQLException public void writeXml(ResultSet rset, java.io.OutputStream ostream) throws SQLException
これらのメソッドは、
OracleWebRowSet
オブジェクトを作成し、そのオブジェクトに指定したResultSet
オブジェクトのデータを移入し、提供されたWriter
またはOutputStream
オブジェクトにJSR-114 XMLスキーマ準拠のXML形式で書き込みます。public void readXml(java.io.Reader reader) throws SQLException public void readXml(java.io.InputStream istream) throws SQLException
これらのメソッドは、提供された
Reader
またはInsputStream
オブジェクトを使用して、OracleWebRowSet
オブジェクトをJSR-114 XMLスキーマ準拠のXML形式で読み取ります。
Oracle WebRowSet実装は、Java API for XML Processing (JAXP) 1.2をサポートしています。Simple API for XML (SAX) 2.0とDocument Object Model (DOM) JAXPのどちらに準拠しているXMLパーサーもサポートされます。WebRowSetの現在のJSR-114 W3C XMLスキーマに準拠します。
readXml(...)
メソッドを使用するアプリケーションの場合は、メソッドのコール前に、次の2つの標準JAXPシステム・プロパティのいずれかを設定する必要があります。
-
javax.xml.parsers.SAXParserFactory
このプロパティは、SAXパーサー用です。
-
javax.xml.parsers.DocumentBuilderFactory
このプロパティは、DOMパーサー用です。
次のコードでは、XML形式での書込みおよび読取り両方にOracleWebRowSet
を使用します。
import java.sql.*; import java.io.*; import oracle.jdbc.rowset.*; ... String url = "jdbc:oracle:oci8:@"; Connection conn = DriverManager.getConnection(url,"HR","hr"); Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery("select * from employees"); // Create an OracleWebRowSet object and populate it with the ResultSet object OracleWebRowSet wset = new OracleWebRowSet(); wset.populate(rset); try { // Create a java.io.Writer object FileWriter out = new FileWriter("xml.out"); // Now generate the XML and write it out wset.writeXml(out); } catch (IOException exc) { System.out.println("Couldn't construct a FileWriter"); } System.out.println("XML output file generated."); // Create a new OracleWebRowSet for reading from XML input OracleWebRowSet wset2 = new OracleWebRowSet(); // Use Oracle JAXP SAX parser System.setProperty("javax.xml.parsers.SAXParserFactory","oracle.xml.jaxp.JXSAXParserFactory"); try { // Use the preceding output file as input FileReader fr = new FileReader("xml.out"); // Now read XML stream from the FileReader wset2.readXml(fr); } catch (IOException exc) { System.out.println("Couldn't construct a FileReader"); } ...
ノート:
前述のコードでは、スキーマの妥当性チェックをサポートするOracle SAX XMLパーサーを使用しています。
18.5 FilteredRowSetについて
FilteredRowSetは、WebRowSetの拡張機能であり、プログラム内容のフィルタリングに必要なプログラム・サポートを提供します。これにより、問合せの指定および関連処理に要するオーバーヘッドを回避できます。FilteredRowSetのOracle実装は、oracle.jdbc.rowset.OracleFilteredRowSet
です。ojdbc7.jar
ファイルのOracleFilteredRowSet
クラスは、標準のJSR-114インタフェースjavax.sql.rowset.FilteredRowSet
を実装します。
OracleFilteredRowSet
クラスは、次の新しいメソッドを定義します。
public Predicate getFilter();
このメソッドは、
OracleFilteredRowSet
オブジェクトでアクティブなフィルタリング基準を定義するPredicate
オブジェクトを戻します。public void setFilter(Predicate p) throws SQLException;
このメソッドは、
Predicate
オブジェクトをパラメータとして取ります。Predicate
オブジェクトは、OracleFilteredRowSet
オブジェクトに適用するフィルタリング基準を定義します。このメソッドでは、SQLException
例外が発生します。
ノート:
FilteredRowSet機能に対してojdbc5.jar
およびojdbc6.jar
のかわりにclasses12.jar
を使用している場合、Predicate
のかわりにOraclePredicate
を使用します。Oracle固有のoracle.jdbc.rowset.OraclePredicate
インタフェースは、Predicate
と同等です。このインタフェースは、JSR-114パッケージを使用できない場合に使用します。
OracleFilteredRowSet
オブジェクトに設定される条件は、参照できる行のセットを取得するためにオブジェクト内の行すべてに適用するフィルタリング基準を定義します。また、行の挿入、削除および変更に適用する基準も定義します。設定されたフィルタリング基準は、OracleFilteredRowSet
オブジェクトの参照および更新すべてに適用されるゲーティング・メカニズムとして機能します。OracleFilteredRowSet
オブジェクトを更新しようとすると、フィルタリング基準に違反するため、SQLException
例外が発生します。
OracleFilteredRowSet
オブジェクトに設定されているフィルタリング基準を変更するには、新しいPredicate
オブジェクトを適用します。新しい基準は即時にオブジェクトに適用されるため、適用以後の参照および更新では、すべてこの新しい基準に準拠する必要があります。新しいフィルタリング基準を適用できるのは、OracleFilteredRowSet
オブジェクトへの参照がない場合のみです。
オブジェクトに設定されたフィルタリング基準の範囲外の行は、そのフィルタリング基準が削除されるか、新しいフィルタリング基準が適用されるまで変更できません。また、このオブジェクトの同期化を続行しても、データソースと同期化される行は、フィルタリング基準の範囲内の行のみです。
次のコードは、OracleFilteredRowSetの使用例を示します。表test_table
に、NUMBER
型のcol1
およびcol2
という2つの列があるものとします。この表からコードが取り出す行には、col1
に50
から100
までの値、col2
に100
から200
までの値が含まれています。
フィルタリング基準を定義する条件を次に示します。
public class PredicateImpl implements Predicate { private int low[]; private int high[]; private int columnIndexes[]; public PredicateImpl(int[] lo, int[] hi, int[] indexes) { low = lo; high = hi; columnIndexes = indexes; } public boolean evaluate(RowSet rs) { boolean result = true; for (int i = 0; i < columnIndexes.length; i++) { int columnValue = rs.getInt(columnIndexes[i]); if (columnValue < low[i] || columnValue > high[i]) result = false; } return result; } // the other two evaluate(...) methods simply return true }
前述のコードで定義した条件を使用して、OracleFilteredRowSet
オブジェクトの内容を次のようにフィルタリングします。
... OracleFilteredRowSet ofrs = new OracleFilteredRowSet(); int low[] = {50, 100}; int high[] = {100, 200}; int indexes[] = {1, 2}; ofrs.setCommand("select col1, col2 from test_table"); // set other properties on ofrs like usr/pwd ... ... ofrs.execute(); ofrs.setPredicate(new PredicateImpl(low, high, indexes)); // this will only get rows with col1 in (50,100) and col2 in (100,200) while (ofrs.next()) {...} ...
18.6 JoinRowSetについて
JoinRowSetは、WebRowSetの拡張機能であり、異なるRowSetの関連データで構成されています。データソースに接続していない状態では、切断されたRowSet間でSQL JOIN
を確立する標準的な方法はありません。JoinRowSetはこの問題に対応しています。JoinRowSetのOracle実装は、oracle.jdbc.rowset.OracleJoinRowSet
クラスです。このクラスは、ojdbc7.jar
ファイル内にあり、標準のJSR-114インタフェースjavax.sql.rowset.JoinRowSet
を実装します。
Joinable
インタフェースを実装する任意の数のRowSet
オブジェクトは、SQL JOIN
に関連付けることが可能な場合、JoinRowSet
オブジェクトに追加できます。RowSetの5つのタイプはすべて、Joinable
インタフェースをサポートします。Joinable
インタフェースには、JOIN
を実行するときに使用する列(一致する列)を指定するためのメソッドがあります。
ノート:
JoinRowSet機能に対してojdbc5.jar
およびojdbc6.jar
のかわりにclasses12.jar
を使用している場合、Joinable
のかわりにOracleJoinable
を使用します。Oracle固有のoracle.jdbc.rowset.OracleJoinable
インタフェースは、Joinable
と同等です。このインタフェースは、JSR-114パッケージを使用できない場合に使用します。
一致する列は次の方法で指定できます。
-
setMatchColumn
メソッドの使用このメソッドは、
Joinable
インタフェースで定義されます。RowSet
オブジェクトをJoinRowSet
オブジェクトに追加する前に、一致する列の設定に使用できるのは、このメソッドのみです。また、一致する列の再設定にいつでも使用できます。 -
addRowSet
メソッドの使用このメソッドは、
JoinRowSet
でオーバーロードされます。このメソッドの5つの実装のうち4つは、一致する列をパラメータとして取ります。この4つのメソッドを使用して、RowSet
オブジェクトをJoinRowSet
オブジェクトに追加するときに、一致する列を設定または再設定できます。
OracleJoinRowSet
は、継承されるメソッド以外に、次のメソッドを提供します。
public void addRowSet(Joinable joinable) throws SQLException; public void addRowSet(RowSet rowSet, int i) throws SQLException; public void addRowSet(RowSet rowSet, String s) throws SQLException; public void addRowSet(RowSet arowSet[], int an[]) throws SQLException; public void addRowSet(RowSet arowSet[], String as[]) throws SQLException;
これらのメソッドを使用して、
RowSet
オブジェクトをOracleJoinRowSet
オブジェクトに追加します。1つ以上のRowSet
オブジェクトをOracleJoinRowSet
オブジェクトに渡して追加できます。一致する列として設定する必要がある1つ以上の列の名前または索引を渡すこともできます。public Collection getRowSets() throws SQLException;
このメソッドは、
OracleJoinRowSet
に追加されたRowSet
オブジェクトを取り出します。また、RowSet
オブジェクトを含むjava.util.Collection
オブジェクトを戻します。public String[] getRowSetNames() throws SQLException;
このメソッドは、
OracleJoinRowSet
オブジェクトに追加されるRowSet
オブジェクトの名前を含む文字列の配列を戻します。public boolean supportsCrossJoin(); public boolean supportsFullJoin(); public boolean supportsInnerJoin(); public boolean supportsLeftOuterJoin(); public boolean supportsRightOuterJoin();
これらのメソッドは、
OracleJoinRowSet
オブジェクトが、対応するJOIN
型をサポートしているかどうかを示すブール値を戻します。public void setJoinType(int i) throws SQLException;
このメソッドを使用して、
OracleJoinRowSet
オブジェクトにJOIN
型を設定します。このメソッドは、javax.sql.rowset.JoinRowSet
インタフェースで定義されたJOIN
型を指定する整数定数を取ります。public int getJoinType() throws SQLException;
このメソッドは、
OracleJoinRowSet
オブジェクトに設定されたJOIN
型を示す整数値を戻します。このメソッドでは、SQLException
例外が発生します。public CachedRowSet toCachedRowSet() throws SQLException;
このメソッドは、
OracleJoinRowSet
オブジェクトのデータを含むCachedRowSet
オブジェクトを作成します。public String getWhereClause() throws SQLException;
このメソッドは、
OracleJoinRowSet
オブジェクトで使用されるWHERE
句のSQLなどの記述を含む文字列を戻します。このメソッドでは、SQLException
例外が発生します。
次のコードは、OracleJoinRowSet
を使用して、2つの異なる表のデータを含む2つのRowSetで内部結合を実行します。結合されたRowSetには、2つの表で内部結合が実行された場合と同じデータが含まれます。表が2つあり、その一方はNUMBER
型の2つの列Order_id
およびPerson_id
を備えたOrder
表、他方はNUMBER
型の列Person_id
とVARCHAR2
型の列Name
を備えたPerson
表であるものとします。
... // RowSet holding data from table Order OracleCachedRowSet ocrsOrder = new OracleCachedRowSet(); ... ocrsOrder.setCommand("select order_id, person_id from order"); ... // Join on person_id column ocrsOrder.setMatchColumn(2); ocrsOrder.execute(); // Creating the JoinRowSet OracleJoinRowSet ojrs = new OracleJoinRowSet(); ojrs.addRowSet(ocrsOrder); // RowSet holding data from table Person OracleCachedRowSet ocrsPerson = new OracleCachedRowSet(); ... ocrsPerson.setCommand("select person_id, name from person"); ... // do not set match column on this RowSet using setMatchColumn(). //use addRowSet() to set match column ocrsPerson.execute(); // Join on person_id column, in another way ojrs.addRowSet(ocrsPerson, 1); // now we can go the JoinRowSet as usual ojrs.beforeFirst(); while (ojrs.next()) System.out.println("order id = " + ojrs.getInt(1) + ", " + "person id = " + ojrs.getInt(2) + ", " + "person's name = " + ojrs.getString(3)); ...