動的照会サービスの使用
開発プロセスでは、 通常の Enterprise JavaBean (EJB) 照会サービス (デプロイメント照会 とも呼ばれる) でなく、 動的照会サービスを使用した方がいいことがあります。 例えば、テスト中に、動的照会サービスをアプリケーション・ランタイムで使用することができるため、 アプリケーションを再デプロイする必要はありません。
このタスクについて
- デプロイメント時ではなく、アプリケーション実行時に照会をプログラムで定義する必要があります。
- 1 つの照会から複数の CMP または CMR フィールドを戻す必要があります。 (デプロイメント照会では SELECT 文節で 1 つのエレメントしか指定できません。) 詳細については、トピック『例: EJB 照会』を参照してください。
- 照会で計算式を戻したい。
- 照会ステートメントで、値オブジェクト・メソッドまたは Bean メソッドを使用する。 詳細については、トピック『パス式』を参照してください。
- 開発中に EJB 照会を対話式にテストするが、検索照会または選択照会を更新するごとに アプリケーションを繰り返しデプロイしない。
動的照会 API は、Stateless Session Bean です。他の J2EE EJB アプリケーション Bean と同じように使用できます。 この API は API パッケージの com.ibm.websphere.ejbquery に格納されています。
リモート・インターフェース = com.ibm.websphere.ejbquery.Queryリモート・ホーム・インターフェース = com.ibm.websphere.ejbquery.QueryHome
照会からローカル EJB 参照を戻す場合、または照会ステートメントにローカル・メソッドが 含まれる場合は、照会ローカル・インターフェースを使用する必要があります。ローカル・インターフェース = com.ibm.websphere.ejbquery.QueryLocalローカル・ホーム・インターフェース = com.ibm.websphere.ejbquery.QueryLocalHome
ローカル・インターフェースでは、 アプリケーション・サーバー・メモリーをあまり使わないため、リモート・インターフェースよりも全体的な EJB パフォーマンスが向上します。
手順
例
- 動的照会用のリモート・インターフェースの使用。
リモート・インターフェースを使用して動的 Enterprise JavaBeans (EJB) 照会を実行する場合は、 Query インターフェースで executeQuery メソッドを呼び出します。 executeQuery メソッドにはこのインターフェース用の必須トランザクション属性があります。 このため、照会を実行するためにトランザクション・コンテキストを明示的に確立する必要がありません。
リモート・インターフェースを使用して動的 Enterprise JavaBeans (EJB) 照会を実行する場合は、 Query インターフェースで executeQuery メソッドを呼び出します。 executeQuery メソッドにはこのインターフェース用の必須トランザクション属性があります。 このため、照会を実行するためにトランザクション・コンテキストを明示的に確立する必要がありません。
以下のインポート・ステートメントで始めます。
import com.ibm.websphere.ejbquery.QueryHome; import com.ibm.websphere.ejbquery.Query; import com.ibm.websphere.ejbquery.QueryIterator; import com.ibm.websphere.ejbquery.IQueryTuple; import com.ibm.websphere.ejbquery.QueryException;
次に以下の例のように、照会ステートメントをストリングの形で書き込みます。例では低賃金従業員の名前と EJB 参照を検索しています。
String query = "select e.name as name , object(e) as emp from EmpBean e where e.salary < 50000";
QueryHome クラスから参照を取得して、Query オブジェクトを作成します。 (このクラスは executeQuery メソッドを定義します。) 簡素化するために、以下の例では Query オブジェクトに動的照会 JNDI 名を使用していることに注意してください。
InitialContext ic = new InitialContext(); Object obj = ic.lookup("com/ibm/websphere/ejbquery/Query"); QueryHome qh = ( QueryHome) javax.rmi.PortableRemoteObject.narrow( obj, QueryHome.class ); Query qb = qh.create();
次に、照会結果セットに最大のサイズを指定する必要があります。これはクラス QueryIterator に含まれた QueryIterator オブジェクトで定義されます。 次に、照会結果セットの最大のサイズを指定する必要があります。これは、QueryIterator オブジェクトで定義されます。このクラスは、QueryIterator API パッケージに含まれています。 この例では結果セットの最大サイズを 99 に設定しています。
QueryIterator it = qb.executeQuery(query, null, null ,0, 99 );
イテレーターには IQueryTuple オブジェクトのコレクションが含まれています。これらは戻り値のコレクションのレコードです。 照会ステートメントの例の基準に対応して、このシナリオの各タプルには name の値と object(e) の値がそれぞれ 1 つ含まれています。 この照会結果の内容を表示するには、次のコードを使用します。while (it.hasNext()) { IQueryTuple tuple = (IQueryTuple) it.next(); System.out.print( it.getFieldName(1) ); String s = (String) tuple.getObject(1); System.out.println( s); System.out.println( it.getFieldName(2) ); Emp e = ( Emp) javax.rmi.PortableRemoteObject.narrow( tuple.getObject(2), Emp.class ); System.out.println( e.getPrimaryKey().toString()); }
このプログラムからの出力は、次のようなものになります。name Bob emp 1001 name Dave emp 298003 ...
最後に、例外をキャッチして処理します。 照会ステートメントの構文エラーまたはランタイムの処理エラーによって、例外が発生する 場合があります。 次の例ではこれらの例外をキャッチし、処理しています。} catch (QueryException qe) { System.out.println("Query Exception "+ qe.getMessage() ); }
リモート・インターフェース照会での大きな結果コレクションの処理
照会で大きなコレクションの戻り値があると思われる場合、複数のより小さな、より管理しやすい量で結果を戻すようにプログラミングすることができます。 リモートの executeQuery メソッドで skipRow および maxRow パラメーターを使用して、答えを複数の塊でリトリーブします。 以下に例を示します。
int skipRow=0; int maxRow=100; QueryIterator it = null; do { it = qb.executeQuery(query, null, null ,skipRow, maxRow ); while (it.hasNext()) { // display result skipRow = skipRow + maxRow; } } while ( ! it.isComplete() ) ;
- 動的照会用のローカル・インターフェースの使用。
ローカル・インターフェースを使用して動的 Enterprise JavaBeans (EJB) 照会を実行する場合は、 QueryLocal インターフェースで executeQuery メソッドを呼び出します。 このインターフェースはメソッドのトランザクションを開始しません。 このため、照会を実行するにはトランザクション・コンテキストを明示的に確立する必要があります。
注: トランザクション・コンテキストを確立するために、以下の例では begin() メソッドと commit() メソッドを呼び出しています。 これらのメソッドを使用する代わりに、単にトランザクション・コンテキスト内で実行される EJB メソッド内に照会コードを組み込むこともできます。照会コードは以下のようなインポート・ステートメントで始めます。
import com.ibm.websphere.ejbquery.QueryLocalHome; import com.ibm.websphere.ejbquery.QueryLocal; import com.ibm.websphere.ejbquery.QueryLocalIterator; import com.ibm.websphere.ejbquery.IQueryTuple; import com.ibm.websphere.ejbquery.QueryException;
次に以下の例のように、照会ステートメントをストリングの形で書き込みます。例では低賃金従業員の名前と EJB 参照を検索しています。
String query = "select e.name, object(e) from EmpBean e where e.salary < 50000 ";
QueryLocalHome クラスから参照を取得して QueryLocal オブジェクトを作成します。 (このクラスは executeQuery メソッドを定義します。) 以下の例では ejb/query が動的照会の JNDI 名 (com/ibm/websphere/ejbquery/Query) を指すローカル EJB 参照として使用されていることに注意してください。
InitialContext ic = new InitialContext(); QueryLocalHome qh = ( LocalQueryHome) ic.lookup( "java:comp/env/ejb/query" ); QueryLocal qb = qh.create();
コードの最後の部分はトランザクションの開始、executeQuery メソッドの呼び出し、照会結果の表示を行います。 QueryLocalIterator クラスは照会結果セットを定義するため、インスタンス化されます。 このクラスは、クラス QueryIterator API パッケージに含まれています。トランザクションの最後にはイテレーターが有効期間を喪失するため、 executeQuery 呼び出しと同じトランザクションの有効範囲でイテレーターを使用しなければならないことに注意してください。
userTransaction.begin(); QueryLocalIterator it = qb.executeQuery(query, null, null); while (it.hasNext()) { IQueryTuple tuple = (IQueryTuple) it.next(); System.out.print( it.getFieldName(1) ); String s = (String) tuple.getObject(1); System.out.println( s); System.out.println( it.getFieldName(2) ); EmpLocal e = ( EmpLocal ) tuple.getObject(2); System.out.println( e.getPrimaryKey().toString()); } userTransaction.commit();
大抵の場合、QueryLocalIterator オブジェクトは demand-driven です。 つまり、データは増分的に戻されます。データベースからレコードを検索するごとに、イテレーターで next() メソッドが呼び出される必要があります。 (イテレーターが demand-driven でない場合もあります。 詳しくは、動的照会のパフォーマンスに関する考慮事項トピックの『ローカル QUERY インターフェース』サブセクションを参照してください。)
完全な照会結果セットはアプリケーション・サーバー・メモリーで増分的に具体化されるため、そのサイズは簡単に制御することができます。 例えば、テスト実行中に、ユーザーは照会結果のいくつかのタプルのみが戻される必要があると判断する場合もあります。 そのような場合には、QueryLocalIterator オブジェクトの close() メソッド呼び出しを使って照会ループをクローズします。 こうすることによって、イテレーターが使用する SQL リソースが解放されます。 そうしない場合、完全な結果セットがメモリーに累積されるか、トランザクションが終了するまで、これらのリソースは解放されません。