ヘッダーをスキップ
Oracle Containers for J2EE Orion CMP開発者ガイド
10g(10.1.3.1.0)
B31855-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

6 コンテナ管理の永続性を持つエンティティBeanに対する問合せメソッドの実装

エンティティBeanの問合せはfinderメソッドまたはselectメソッドを使用して表すことができます。この章では、Orion EJB 2.0でのEJB QLのfinderメソッドおよびselectメソッドの実装の詳細を説明します。

この章の内容は次のとおりです。

詳細は次のトピックを参照してください。

EJB QLのfinderメソッドの実装

この項の内容は次のとおりです。

finderメソッド(ejbFind)はエンティティBeanへの問合せを行う検索基準を定義します(詳細は「finderメソッドの理解」を参照)。

finderメソッドを定義するには次の手順を実行します。

  1. 対象のホーム・インタフェースでfind<NAME>メソッドを定義します。リモートまたはローカルのホーム・インタフェースで異なるfinderメソッドを指定できます。両方のホーム・インタフェースで同じfinderメソッドを定義した場合、同じエンティティBeanクラス定義にマップされます。コンテナは該当するホーム・インタフェース・タイプを返します。

  2. finderメソッドに対する完全な問合せまたは条件文(WHERE句)のみをデプロイメント・ディスクリプタで定義します。

    EJB QL構文またはOC4J固有構文のどちらかを使用して問合せを定義できます。完全な問合せ、または問合せの条件部分(WHERE句)のみのどちらかを指定します。

    • EJB QL構文はejb-jar.xmlファイル内で定義されます。EJB QL文は各finderメソッドに対し、その<query>要素内に作成されます。コンテナはこの文を使用して、エンティティBean参照の取得方法の条件を、関連するSQL文に変換します。


      注意:

      EJB 2.0では、AVERAGESUMなど、GROUP BYおよびORDER BY関数に対するEJB QLのサポートは制限されています。

      詳細は「EJB QL構文を使用したfinderメソッドの指定」を参照してください。

    • OC4J固有構文はorion-ejb-jar.xmlファイル内で定義されます。アプリケーションをデプロイするとき、OC4JはEJB QL構文をOC4J固有構文に変換します。構文は、<finder-method>要素のquery属性で指定されます。OC4J構文を使用することで、より複雑な問合せに対してquery属性の文を変更できます。orion-ejb-jar.xmlファイルのOC4J固有問合せ文は、ejb-jar.xmlファイルの対応するEJB QL文よりも優先されます。

      詳細は「OC4J固有構文を使用したfinderメソッドの指定」を参照してください。


注意:

finderメソッドはFinderExceptionをスローします。

1つのエンティティBean参照のみを取得する場合、コンテナはfind<NAME>メソッドで返されたものと同じ型を返します。複数のエンティティBean参照をリクエストする場合、Collectionを返すようにfind<NAME>メソッドの戻り型を定義する必要があります。重複するものが返されないようにするには、EJB QL文でDISTINCTキーワードを指定します。一致するものが見つからない場合は空のCollectionが返されます。

EJB QL構文を使用したfinderメソッドの指定

EJB QL構文を使用したfinderメソッドの作成には2つのステップがあります。

  1. ホーム・インタフェースにおけるfinderメソッドの定義

  2. デプロイメント・ディスクリプタを使用したfinderメソッド定義の指定

ホーム・インタフェースにおけるfinderメソッドの定義

finderメソッドをホーム・インタフェースに追加する必要があります。たとえば、すべての従業員を取得する場合、ホーム・インタフェース(この例ではローカル・ホーム・インタフェース)でfindAllメソッドを定義します。

public Collection findAll() throws FinderException

1人の従業員に対するデータを取得するには、ホーム・インタフェースでfindByEmployeeNumberメソッドを定義します。

public EmployeeLocal findByEmployeeNumber(Integer empNumber) throws FinderException;

前述の例では、返されるBeanインタフェースはローカル・インタフェースのEmployeeLocalです。入力パラメータは従業員番号のempNumberで、これはEJB QLの?1パラメータで置き換えられます。

デプロイメント・ディスクリプタを使用したfinderメソッド定義の指定

各finderメソッドはデプロイメント・ディスクリプタの<query>要素で定義されます。findByEmployeeNumberメソッドに対するデプロイメント・ディスクリプタの例を次に示します。

<query>
  <description></description>
  <query-method>
    <method-name>findByEmployeeNumber</method-name>
    <method-params>
      <method-param>java.lang.Integer</method-param>
    </method-params>
  </query-method>
  <ejb-ql>SELECT OBJECT(e) FROM Employee emp WHERE emp.empNumber = ?1</ejb-ql>
</query>

findByEmployeeNumberメソッドに対するEJB QL文ではEmployeeオブジェクトが選択され、ここで従業員番号はEJB QLの?1パラメータで置き換えられます。?という記号はメソッド・パラメータに対するプレースホルダを表します。このため、findByEmployeeNumberメソッドでは少なくとも1つのパラメータを指定することが必要です。findByEmployeeNumberメソッドに渡されたempNumberは、ここで?1の位置に置き換えられます。変数empは、WHERE条件におけるEmployeeオブジェクトを識別します。

OC4J固有構文を使用したfinderメソッドの指定

OC4J固有構文を使用したfinderメソッドの作成には2つのステップがあります。

  1. ホーム・インタフェースへのfinderメソッドの追加

  2. OC4J固有デプロイメント・ディスクリプタを使用したfinderメソッドの定義

ホーム・インタフェースへのfinderメソッドの追加

最初にfinderメソッドをホーム・インタフェースに追加する必要があります。たとえば、EmployeeエンティティBeanですべての従業員を取得するには、ホーム・インタフェース内でfindAllメソッドを次のように定義します。

public Collection findAll() throws FinderException, RemoteException;

OC4J固有デプロイメント・ディスクリプタを使用したfinderメソッドの定義

ホーム・インタフェースでfinderメソッドを指定した後、finderメソッドの問合せを追加してorion-ejb-jar.xmlファイルを変更します。

<finder-method>要素はfindByPrimaryKeyメソッド以外のすべてのfinderメソッドを定義します。定義が一番単純なfinderメソッドはfindAllメソッドです。<finder-method>要素のquery属性は、完全な問合せまたは問合せのWHERE句のみを指定できます。すべての行を取得する場合は、すべてのレコードを返す空の問合せ(query="")を指定します。

OC4J固有finderメソッドは、orion-ejb-jar.xmlファイルの<finder-method>要素で構成されます。各<finder-method>要素では、query属性で一部または完全なSQL文を指定します。

/*the empty WHERE clause finds all*/
<finder-method query="">

または

/*finds all records where employee equals the first input parameter*/
<finder-method query="$empName=$1">

query属性を持つ<finder-method>要素がある場合、ejb-jar.xmlファイルの同じメソッドに対するEJB QLの変更よりも優先されます。

複合的なfinderメソッドを定義するには次の手順を実行します。

  1. ejb-jar.xmlファイルで、EJB QLを使用した単純な問合せを定義します。

  2. アプリケーションをデプロイします。デプロイの際に、OC4JはEJB QL文をOC4J固有の対応する文に変換します。実行される完全な基礎SQL文はコメントで表示されます(例6-1「findAllメソッドのためのOC4J固有構文」を参照)。

  3. 目的の複合レベルに達するように、orion-ejb-jar.xmlファイルで<finder-method>要素のquery属性を変更します。再デプロイの際に、OC4Jは新規の問合せを変換し、実行されるSQL文とともに新規のコメントを出力します。コメントをチェックして、構文が正しいことを確認します。

EJB QL構文を使用するときにorion-ejb-jar.xmlファイルに既存の定義がある場合は、次の手順を実行します。

  1. orion-ejb-jar.xmlファイルで<finder-method>要素のquery属性を削除します。

  2. アプリケーションを再デプロイします。OC4Jでは<finder-method>要素のquery属性が存在しないことが認識され、かわりにejb-jar.xmlファイルのEJB QLのメソドロジが使用されます。


警告:

CMRに関わる複合的問合せの実行時に、OC4Jが部分的なfinderメソッドの問合せに基づいてSQL文を生成する方法には制約があります。たとえば、CMR結合間を間接参照するための記述はありません。コンテナ管理の関連の列を処理する際には、<finder-method>要素のpartial属性をfalseに設定してRAW SQLを使用する必要があります。部分的問合せの詳細は、「要素の説明」例6-3を参照してください。

この制約は、EJB 2.0仕様でLIKE句をサポートしていないことが原因の一部です。


例6-1 findAllメソッドのためのOC4J固有構文

例6-1EmployeeBeanからのすべてのレコードの取得を示しています。finderメソッド名はfindAllです。このメソッドはすべての従業員のCollectionを返すため、パラメータが不要です。

<finder-method query="">
<!-- Generated SQL: "select EmployeeBean.empNumber,
      EmployeeBean.empName, EmployeeBean.salary from EmployeeBean" -->
    <method>
        <ejb-name>EmployeeBean</ejb-name>
        <method-name>findAll</method-name>
            <method-params></method-params>
    </method>
</finder-method>


注意:

問合せに詳細を追加する場合は、適切なWHERE句でquery属性を変更できます。この句は渡されたパラメータをドル( $ )記号を使用して参照します。たとえば1番目のパラメータは$1、2番目のパラメータは$2、などのように表されます。WHERE句内で使用されるすべての<cmp-field>要素は$<cmp-field>名で表されます。

例6-2 findByNameメソッドのためのOC4J固有構文

例6-2findByNameメソッド(ホーム・インタフェースで定義されます)の詳細を示しています。従業員の名前はメソッド・パラメータで与えられ、$1に置き換えられます。これはempNameというCMP名に一致します。このため、query属性はWHERE句に対する$empName=$1を含むように変更されます。

<finder-method query="$empName=$1">
    <method>
        <ejb-name>EmployeeBean</ejb-name>
        <method-name>findByName</method-name>
        <method-params>
            <method-param>java.lang.String</method-param>
        </method-params>
    </method>
</finder-method>

注意:

複数のメソッド・パラメータがある場合は、後続の<method-param>要素で各パラメータ型を定義し、問合せ文で後続の$nnは番号を表す)によりこれを参照します。


注意:

SQL JOINquery属性で指定できます。

例6-3 完全な問合せのためのOC4J固有構文

例6-3は、WHERE句の後のセクションのみでなく、完全な問合せを指定する例を示しています。この場合は、partial属性をfalseに設定してから、query属性で完全な問合せを定義する必要があります。partial属性のデフォルト値はtrueです(これが例6-2で指定されない理由です)。

<finder-method partial="false" query="select * from emp where $empName=$1">
    <!-- Generated SQL: "select * from emp where emp.empName=?" -->
    <method>
        <ejb-name>EmployeeBean</ejb-name>
        <method-name>findByName</method-name>
        <method-params>
            <method-param>java.lang.String</method-param>
        </method-params>
    </method>
</finder-method>

注意:

生成されたSQL文を部分的なfinderメソッドの問合せに対するベースとして使用する場合は、次のことを確認してください。
  • SQL固有の?プレースホルダが$n位置パラメータに変換されていること

  • ><>=などの特定のXML文字がエスケープされていること


例6-4 遅延ロードを有効にするためのOC4J固有構文

エンティティBeanのfinderメソッドでは、遅延ロードでselectメソッド(「selectメソッドの理解」を参照)が複数回起動される場合があります。デフォルトでは、遅延ロードはオフになっています。多数のオブジェクトを取得するときにその中のいくつかのみにアクセスする場合は、例6-4のように、lazy-loadingプロパティをtrueに設定して遅延ロードをオンにします。

<finder-method partial="false" query="select * from emp where $empName=$1"
lazy-loading=true>
    <!-- Generated SQL: "select * from emp where emp.empName=?" -->
    <method>
        <ejb-name>EmployeeBean</ejb-name>
        <method-name>findByName</method-name>
        <method-params>
            <method-param>java.lang.String</method-param>
        </method-params>
    </method>
</finder-method>

例6-5 フェッチ・サイズを設定するためのOC4J固有構文

例6-5のようにprefetch-size属性を設定して、JDBCドライバが1回にフェッチする行数を定義できます。

<finder-method partial="false" query="select * from emp where $empName=$1"
prefetch-size="15">
    <!-- Generated SQL: "select * from emp where emp.empName=?" -->
    <method>
        <ejb-name>EmployeeBean</ejb-name>
        <method-name>findByName</method-name>
        <method-params>
            <method-param>java.lang.String</method-param>
        </method-params>
    </method>
</finder-method>

Oracle JDBCドライバには、問合せ中に結果セットが移入されている間、クライアントにプリフェッチする行数を、ユーザーが設定できるようにする拡張機能が含まれています。これによって、データがフェッチされるときは複数のデータ行がフェッチされるため、データベースへのラウンドトリップが減少します(追加データはクライアントによる以後のアクセスのため、クライアント側バッファに格納されます)。プリフェッチする行数はユーザーの希望どおりに設定できます。クライアントにプリフェッチする行数のデフォルトは10です。この数字はJDBCドライバに渡されます。

EJB QLのselectメソッドの実装

selectメソッド(ejbSelect)は、エンティティBean参照、あるいはコンテナ管理の永続性または関連フィールドの値を取得するために使用されます(「selectメソッドの理解」を参照)。

ejbSelectメソッド定義の書式を次に示します。

public abstract type ejbSelect<METHOD>(...);

selectメソッドは、起動されるエンティティBeanインスタンスのIDをベースにはしませんが、エンティティBeanの主キーを引数として使用できます。これによって、特定のエンティティBeanインスタンスが論理的な対象となる問合せが作成されます。selectメソッドの戻り型の定義方法の詳細は、「selectメソッドに対する戻り型の定義」を参照してください。

selectメソッドを定義するには次の手順を実行します。

  1. 各selectメソッドに対するBeanクラスでejbSelect<NAME>メソッドを定義します。各メソッドはpublic abstractとして定義されます。このメソッドに必要なSQLは実装に含まれません。

  2. selectメソッドに対する完全な問合せまたは条件文のみ(WHERE句)をデプロイメント・ディスクリプタで定義します。EJB QL文は、各selectメソッドの<query>要素に作成されます。コンテナはこの文を使用して、条件を関連するSQL文に変換します。


注意:

finderメソッドの場合のように、orion-ejb-jar.xmlファイルでejbSelectメソッドに対する問合せ文を変更することはできません。

例6-6 Beanクラスにおけるselectメソッドの定義

例6-6は、指定した範囲内の給与を支給されているすべての従業員を取得するselectメソッドの定義を示しています。

public abstract Collection ejbSelectBySalaryRange(Float s1, Float s2) throws FinderException;

前述のselectメソッドは複数の従業員を取得するため、Collectionが返されます。給与範囲の最低値および最高値が入力パラメータで、これはEJB QLの?1および?2パラメータで置き換えられます。1番目の入力パラメータは?1で返され、2番目の入力パラメータは?2で返されます。宣言されたすべてのメソッド・パラメータの順序は、?1?2?nのEJB QLパラメータの順序と同じです。

例6-7 デプロイメント・ディスクリプタにおけるselectメソッド定義の指定

各selectメソッドはデプロイメント・ディスクリプタの<query>要素で定義されます。例6-7は、例6-6のBeanクラスで定義されたejbSelectBySalaryRangeメソッドに対するデプロイメント・ディスクリプタを示しています。

<query>
    <description></description>
    <query-method>
        <method-name>ejbSelectBySalaryRange</method-name>
        <method-params>
            <method-param>java.lang.Float</method-param>
            <method-param>java.lang.Float</method-param>
        </method-params>
    </query-method>
    <ejb-ql>SELECT DISTINCT OBJECT(emp) From Employee emp
            WHERE emp.salary BETWEEN ?1 AND ?2</ejb-ql>
</query>

ejbSelectBySalaryRangeメソッドにはFLOAT型の2つの入力パラメータがあります。これらの所定入力パラメータの型は<method-param>要素で定義されます。

EJB QLは<ejb-ql>要素で定義されます。ejbSelectBySalaryRangeメソッドは、EJB QL文内で給与の永続フィールドをemp.salaryによって評価します。empEmployeeオブジェクトを表し、salaryはそのオブジェクト内の永続フィールドを表します。この2つを区切るピリオドは、エンティティBeanとその永続フィールドとの関連を示しています。

2つの入力パラメータは給与範囲の最低値および最高値を表し、それぞれ?1および?2の位置に置き換えられます。

ejbSelectBySalaryRangeメソッドはオブジェクトを返します。ここではDISTINCTキーワードにより、重複レコードを返しません。


注意:

selectメソッドはFinderExceptionをスローします。

selectメソッドに対する戻り型の定義

selectメソッドに対する戻り型を定義する際に、検討が必要な条件の一覧を次に示します。

  • selectメソッドによってオブジェクトが見つからない場合は、FinderExceptionが発生します。

  • selectメソッドで1つのオブジェクトを検索する場合、コンテナはejbSelect<NAME>メソッドで返されたものと同じ型を返します。複数のオブジェクトが返された場合はFinderExceptionが発生します。

  • selectメソッドで複数のオブジェクトを検索する場合、ユーザーはejbSelect<NAME>メソッドの戻り型をSetまたはCollectionのどちらかに定義する必要があります。Setは重複を排除します。Collectionには重複が含まれる場合があります。たとえば、すべての顧客のすべての郵便番号を取得する場合は、Setを使用して重複を排除します。すべての顧客の名前を取得するには、Collectionを使用してすべてのリストを取得します。一致するものが見つからない場合は空のCollectionまたはSetが返されます。

    • selectメソッドでBeanインタフェースが返された場合、SetまたはCollection内に返されるデフォルトのインタフェース型はローカルBeanインタフェースです。これは、次のように<result-type-mapping>要素でリモートBeanインタフェースに変更できます。

      <result-type-mapping>Remote</result-type-mapping>
      
      
    • selectメソッドがCMP値のSetまたはCollectionを返す場合、コンテナはEJB QLのselect文からオブジェクト型を判断します。