Sun ONE ロゴ     前へ      目次      索引      次へ     
Sun ONE Application Server 7 Enterprise Java Beans 開発者ガイド



エンティティ Beans の使用

この章では、エンティティ Beans について、および Sun ONE Application Server 7 環境でエンティティ Beans を作成する際の要件について説明します。



エンティティ Beans または EJB テクノロジに精通していない場合は、Java Software チュートリアルを参照してください。

    http://java.sun.com/j2ee/docs.html

エンティティ Beans に関する詳細情報は、『Enterprise JavaBeans Specification, v2.0』の第 9 章、第 10 章、第 12 章、第 13 章、および第 14 章にあります。

Sun ONE Application Server の概要は、「Sun ONE Application Server Enterprise JavaBeans の紹介」および『Sun ONE Application Server Product Introduction』にあります。



この節には次の項目があります。

エンティティ Beans について

エンティティ Bean は、基礎となるデータベースに格納されているエンティティのオブジェクトビュー、または既存のエンタープライズアプリケーション (メインフレームプログラムや ERP アプリケーションなど) によって実装されるエンティティを実装します。たとえば、ビジネスオブジェクトには、顧客、注文、製品などがあります。エンティティ Bean のインスタンスと基本となるデータベースの間でエンティティの状態を転送するためのデータアクセスプロトコルを、オブジェクト持続性と呼びます。

この節では次の項目について説明します。

エンティティ Beans の特性

エンティティ Beans は、いくつかの点でセッション Beans と異なります。エンティティ Beans には持続性があり、複数のクライアントからの同時アクセスに対応しています。また、主キーを持ち、その他のエンティティ Beans との関係を持つこともできます。

エンティティ Beans には次の特性があります。

  • データベース内のデータのオブジェクトを表示する
  • 複数のユーザーによる共有アクセスが可能である
  • Bean 管理持続性またはコンテナ管理持続性を使用して、すべてのクライアントにとって不要になるまで持続する
  • サーバークラッシュを透過的に回避する
  • データベースの共有データを表示する

データベース、ドキュメントなどのビジネスオブジェクトを対象とする、カプセル化された持続トランザクション対話は、エンティティ Bean に適しています。

コンテナ

エンティティ Beans は、コンテナが管理するエンティティオブジェクトのセキュリティ、同時性、トランザクション、および他のコンテナ固有のサービスを管理するようにエンティティ Bean コンテナに要求します。複数のクライアントによるエンティティオブジェクトへの同時アクセスが可能であり、コンテナは、トランザクションを介した同時アクセスを透過的に処理します。

各エンティティ Bean は、一意のオブジェクト ID を持ちます。たとえば、顧客のエンティティ Bean を顧客番号によって識別することができます。この一意の ID、すなわち主キーにより、クライアントは特定のエンティティ Bean を見つけることができます。

セッション Bean と同様に、エンティティ Bean は配備記述子を使ってトランザクション属性を設定できるメソッドに含まれる JDBC 呼び出しを介してデータベースにアクセスすることができます。次で説明するように、このコンテナは、Bean 管理による持続性とコンテナ管理による持続性の両方をサポートします。

持続性

エンティティ Bean の状態は永続的なストレージに保存されるので、持続的です。持続性とは、そのエンティティ Bean の状態が、アプリケーションまたはサーバープロセスの存続期間を超えて存在することを意味します。

エンティティ Beans の持続性は、Bean によって明示的に実現され、Bean 開発者によってプログラムされます。これを BMP (Bean 管理による持続性) と呼びます。

Sun ONE Application Server と Enterprise JavaBeans の持続性管理 API を活用し、持続性の管理をコンテナに任せることもできます。これを CMP (コンテナ管理による持続性) と呼びます。CMP メカニズムによって信頼性の高い持続性を確保するには、Sun ONE Application Server に統合されている持続性マネージャが必要です。コンテナ管理による持続性の詳細については、「エンティティ Beans のコンテナ管理による持続性の使用」を参照してください。

次の図は、Sun ONE Application Server 環境で持続性がどのように機能するかを示しています。


GeBeB Beans t[} (}l[WAgUNV}l[WABMP/CMP BeansAf[^x[X)

自分のアプリケーションに最も適した持続性メソッドを選択するガイドラインについては、「エンティティ Bean の使用法の決定」を参照してください。

この節では次のトピックについて説明します。

Bean 管理による持続性

Bean 管理による持続性では、Bean の持続性を Bean 自身が管理します。エンティティ Bean のコードには、データベースにアクセスする呼び出しを記述します。

開発者は、JDBC と SQL を介して、データベースアクセス呼び出しを Bean クラスのメソッドに直接提供することによって、Bean 管理エンティティ Bean をコード化します。データベースアクセス呼び出しは、ejbCreateejbRemoveejbFindXXXejbLoad、およびejbStore の各メソッドに存在している必要があります。この方法には、これらの Beans をアプリケーションサーバーに簡単に配備できるという利点があります。欠点は、データベースへのアクセスが高コストになることです。データベースへのアクセスの最適化は、場合によってはアプリケーションプログラマが行うよりも、アプリケーションサーバーが行うほうが適しています。また、Bean 管理による持続性では、JDBC コードを記述する必要があります。

JDBC を使ったデータ処理の詳細は、Sun ONE Application Server の『Developerユs Guide to J2EE Features and Services』を参照してください。

コンテナ管理による持続性

コンテナ管理による持続性では、Enterprise JavaBean コンテナが、持続性マネージャを介して、エンティティ Bean が要求するすべてのデータベースアクセスを処理します。この Bean のコードには、データベースアクセス (JDBC) 呼び出しは含まれません。したがって、Bean のコードが特定の永続的なストレージメカニズム (データベース) に結び付けられることはありません。この柔軟性により、同じエンティティ Bean を別のデータベースに再配備する場合でも、Bean のコードを修正する必要がありません。つまり、エンティティ Beans は移植性に優れています。

Bean の開発者は、抽象的な Bean クラスを用意する必要があります。一般に、コンテナ管理による持続性では、実行時に、Bean の状態の読み込みと保存の方法 (ejbLoad メソッドと ejbStore メソッド) を知る具体的な実装クラスが生成されます。

データアクセス呼び出しを生成する場合、コンテナは、エンティティ Bean の抽象スキーマに指定された情報を必要とします。抽象スキーマの詳細については、「抽象スキーマ」を参照してください。

読み取り専用 Beans

読み取り専用 Bean は、EJB クライアントが変更できないエンティティ Bean です。ただし、読み取り専用 Bean が表すデータは、ほかの Enterprise JavaBeans や、データベースの直接更新などの方法によって、外部から更新される場合があります。



Sun ONE Application Server の今回のリリースでは、Bean 管理による持続性を使用するエンティティ Beans のみを読み取り専用として指定できます。



読み取り専用 Bean は、基になるデータがまったく変更されないか、まれにしか変更されない場合に最も適しています。読み取り専用 Bean の作成手順は、「読み取り専用 Beans の使用」を参照してください。

エンティティ Beans の開発

エンティティ Bean を作成するときは、いくつかのクラスファイルを準備する必要があります。次の各項目では、必要な作業について説明します。

エンティティ Bean の使用法の決定

Bean がプロシージャではなくビジネスエンティティを表す場合、または Bean の状態を持続的にする (サーバーがシャットダウンされても Bean の状態がデータベースに存在する) 必要がある場合、あるいはその両方に該当する場合は、エンティティ Bean を使用する必要があります。

セッション Beans とは異なり、エンティティ Bean のインスタンスには、複数のクライアントが同時にアクセスできます。インスタンスの状態の同期は、コンテナがトランザクションを使って行います。この役割がコンテナに委ねられているので、開発者は、複数のトランザクションからの同時アクセスメソッドについて考える必要がありません。

選択する持続性メソッドによっても、次のような影響があります。

  • Bean 管理による持続性 - エンティティ Bean を実装してその Bean 自体の持続性を管理する場合は、EJB クラスメソッドに持続性コード (JDBC 呼び出しなど) を直接実装する。その場合、ダウンサイドでは移植性が失われるため、Bean が特定のデータベースに関連付けられるというリスクがある
  • コンテナ管理による持続性 - エンティティ Bean の持続性をコンテナで管理する場合は、コンテナが透過的に持続性状態を管理するその場合、Bean メソッドのデータアクセスコードを実装する必要はない。この方法は実装が簡単なだけでなく、Bean を別のデータベースに移植できる利点がある。実装のガイドラインについては、「エンティティ Beans のコンテナ管理による持続性の使用」を参照

Bean 開発者の役割

ここでは、持続性を Bean で管理するエンティティ Bean をSun ONE Application Server に配備する上で必要な処理について説明します。

エンティティ Bean の開発者は、次のクラスファイルを用意する必要があります。

  • 主キークラス
  • エンティティ Bean がリモートクライアントビューを提供する場合は、エンティティ Bean のリモートインタフェースとリモートホームインタフェース
  • エンティティ Bean がローカルクライアントビューを提供する場合は、エンティティ Bean のローカルインタフェースとローカルホームインタフェース
  • エンティティ Bean クラス

主キークラスの定義

EJB アーキテクチャでは、RMI-IIOP の タイプが正しいクラスであれば、任意のクラスを主キークラスにできます。このクラスは、hashCode メソッドと equals (Object other) メソッドの実装を提供する必要があります。主キークラスを特定のエンティティ Bean クラス専用にして、エンティティ Bean クラスごとに異なるクラスを主キーとして定義できますが、複数の エンティティ Beans が同じ主キークラスを使うこともできます。

開発者は、主キークラスを配備記述子に指定する必要があります。

リモートインタフェースの定義

この節では、次の項目について説明します。

リモートホームインタフェースの作成

Bean 開発者は、必要に応じて Bean のリモートホームインタフェースを作成する必要があります。ホームインタフェースは、クライアントがアプリケーションにアクセスしてエンティティオブジェクトを作成、検索、および削除するためのメソッドを定義します。作成するリモートホームインタフェースは、次の要件を満たす必要があります。

  • インタフェースは javax.ejb.EJBHome インタフェースを拡張する必要がある
  • このインタフェースに定義されるメソッドは、RMI/IIOP のルールに従う必要がある。つまり、引数と戻り値が正しいタイプの RMI-IIOP で、throws 句が java.rmi.RemoteException を含んでいる必要がある
  • リモートホームインタフェースに定義されるメソッドが、次のいずれかに該当する必要がある
    • create メソッド
    • リモートホームインタフェースには、常に 1 つのオブジェクトを検索する findByPrimaryKey メソッドを含める必要がある。このメソッドは、メソッド引数として主キークラスを宣言する必要がある
    • 検索メソッド
    • home メソッド。create、find、remove メソッドの名前と重複しない限り、home メソッドには任意の名前をつけられる。エンティティ Bean クラスに指定される、一致する ejbHome メソッドは、Bean のリモートホームインタフェースに指定される home メソッドと同じ数とタイプの引数を持ち、同じタイプの戻り値を返す必要がある

リモート Create メソッド

  • create メソッドには、createXXX という名前をつける必要がある。XXX は、Enterprise JavaBean クラスに定義されるいずれかの ejbCreateXXX メソッドと一致する一意のメソッド名の一部である。たとえば、createEmployee(...)createLargeOrder(....) のような名前をつける
  • Bean 内の一致する ejbCreateXXX は、同じ数とタイプの引数を持つ必要がある。ただし、戻り値のタイプは異なる
  • createXXX メソッドの戻り値タイプは、エンティティ Bean のリモートインタフェースのタイプと同じである必要がある
  • Enterprise JavaBean クラスの一致する ejbCreateXXX および ejbPostCreateXXX メソッドの throws 句で定義されるすべての例外は、リモートホームインタフェースの一致する create メソッドの throws 句にも含まれる必要がある。つまり、create メソッドに定義される一連の例外は、ejbCreateXXX および ejbPostCreateXXX メソッド用に定義されるすべての例外のスーパーセット (上位集合) である必要がある
  • create メソッドの throws 句には、javax.ejb.CreateException を含める必要がある

リモート find メソッド

  • ホームインタフェースは、1 つまたは複数の find メソッドを定義できる。各メソッドには findXXX という名前をつける必要がある。XXX は、一意のメソッド名の一部である。たとえば、findApplesAndOranges のような名前をつける
  • 各検索メソッドは、エンティティ Bean のクラス定義で定義された検索メソッドの 1 つと一致する必要がある
  • その数および引数のタイプも Bean クラスの検索メソッド定義と一致する必要がある
  • 1 つのオブジェクトを検索する検索の場合、find <METHOD> メソッドの戻り値のタイプは、エンティティ Bean のリモートインタフェースのタイプと一致する必要がある。複数のオブジェクトを検索する検索では、そのコレクションと一致する必要がある
  • エンティティ Bean クラスの ejbFind メソッドの throws 句で定義されるすべての例外は、リモートホームインタフェースの、一致する find メソッドの throws 句にも含まれている必要がある
  • 検索メソッドの throws 句には、javax.ejb.FinderException を含める必要がある

findByPrimaryKey メソッド

  • すべてのリモートホームインタフェースには、常に 1 つのオブジェクトを検索する findByPrimaryKey メソッドを含める必要がある
  • このメソッドは、メソッド引数として主キークラスを宣言する必要がある
  • エンティティ Bean クラスの ejbFindByPrimaryKey メソッドの throws 句で定義されるすべての例外は、リモートホームインタフェースの、一致する find メソッドの throws 句にも含まれている必要がある
  • findByPrimaryKey メソッドの throws 句には、javax.ejb.FinderException を含める必要がある

リモート remove メソッド

すべてのホームインタフェースには、不要になった Enterprise JavaBean を破棄する 2 つの remove メソッドが javax.ejb.EJBHome の拡張によって自動的に定義されます。

public void remove(java.lang.Object primaryKey)
throws java.rmi.RemoteException,   RemoveException

public void remove(Handle handle)
throws java.rmi.RemoteException,   RemoveException



これらの remove メソッドはオーバーライドしないでください。



リモートホームインタフェースの例


import javax.ejb.*;
import java.rmi.*;

public interface MyEntityBeanLocalHome
   extends EJBHome
{
   /**
       * Create an Employee
       * @param empName Employee name
       * @exception CreateException If the employee cannot be
          created
          * @return The remote interface of the bean
       */
   public MyEntity create(String empName)
       throws CreateException;
   /**
       * Find an Employee
       * @param empName Employee name
       * @exception FinderException if the empName is not found
       * @return The remote interface of the bean
       */
   public MyEntity findByPrimaryKey(String empName)
       throws FinderException;
}

ローカルインタフェースの定義

ローカルアクセスが可能な Enterprise JavaBean を作成するには、ローカルインタフェースおよびローカルホームインタフェースをコーディングする必要があります。ローカルインタフェースは Bean のビジネスメソッドを定義し、ローカルホームインタフェースは Bean のライフサイクル (作成/削除) および検索メソッドを定義します。

この節には次のトピックがあります。

ローカルホームインタフェースの作成

ホームインタフェースは、クライアントがアプリケーションを使ってエンティティ Beans の作成および削除を行うためのメソッドを定義します。Bean のローカルホームインタフェースでは、ローカルクライアントが EJB オブジェクトの作成、検索、および削除を行うことができるようにするメソッドと、Bean インスタンス固有ではないホームビジネスメソッド (セッション Beans が検索メソッドとホームビジネスメソッドを持たない) を定義します。ローカルホームインタフェースは、開発者によって定義され、コンテナによって実装されます。クライアントは、JNDI を使用して Bean のホームインタフェースを検索します。

ローカルホームインタフェースでは、ローカルクライアントは次の操作を実行できます。

  • ホーム内でのエンティティオブジェクトの新規作成
  • ホーム内での既存のエンティティオブジェクトの検索
  • ホームからのエンティティオブジェクトの削除
  • ホームビジネスメソッドの実行

ローカルホームインタフェースは通常、javax.ejb.EJBLocalHome を拡張します。次に例を示します。

   import javax.ejb.*;
   public interface MyEntityLocalBeanHome extends EJBLocalHome {
       MyEntityLocalBean create() throws CreateException;
   }

ローカルインタフェースの作成

エンティティ Bean がコンテナ管理関係のターゲットである場合、そのエンティティ Bean はローカルインタフェースを持つ必要があります。Bean がターゲットであるかどうかは、関係の方向によって決まります。それらのエンティティ Beans はローカルアクセスを必要とするので、コンテナ管理関係に関与するエンティティ Beans は同じ EJB JAR ファイル内に置く必要があります。同じ場所に置くことによる主な利点は、ローカル呼び出しはリモート呼び出しよりも高速であるため、パフォーマンスを向上できることです。

ローカルインタフェースでは、参照セマンティクスによる値の受け渡しが許可されるので、ローカルインタフェースを通して渡されるオブジェクトは共有される可能性があることに注意する必要があります。特に、ある Enterprise JavaBean の状態が別の Enterprise JavaBean の状態として割り当てられないように注意します。また、トランザクションまたはセキュリティの内容に変化がある場合は特に、ローカルインタフェースを通して渡すオブジェクトを決定する際にも注意が必要です。

  • インタフェースは javax.ejb.EJBLocalHome インタフェースを拡張する必要がある
  • ローカルインタフェースに含まれるメソッドの throws 句に、java.rmi.RemoteException を含めることはできない
  • ローカルホームインタフェースに定義されるメソッドが、次のいずれかに該当する必要がある
    • create メソッド
    • 検索メソッド
    • home メソッド。

(ローカル) create メソッド

  • create メソッドには、createXXX という名前をつける必要がある。XXX は、Enterprise JavaBean クラスに定義されるいずれかの ejbCreateXXX メソッドと一致する一意のメソッド名の一部である。たとえば、 createEmployee(...)createLargeOrder(....) のような名前をつける
  • Bean 内の一致する ejbCreateXXX は、同じ数とタイプの引数を持つ必要がある。ただし、戻り値のタイプは異なる
  • createXXX メソッドの戻り値タイプは、エンティティ Bean のローカルインタフェースのタイプと同じである必要がある
  • Enterprise JavaBean クラスの一致する ejbCreateXXX および ejbPostCreateXXX メソッドの throws 句で定義されるすべての例外は、リモートホームインタフェースの一致する create メソッドの throws 句にも含まれる必要がある。つまり、create メソッドに定義される一連の例外は、ejbCreateXXX および ejbPostCreateXXX メソッド用で定義されるすべての例外のスーパーセット (上位集合) である必要がある
  • create メソッドの throws 句には、javax.ejb.CreateException を含める必要がある

(ローカル) find メソッド

  • ホームインタフェースは、1 つまたは複数の find メソッドを定義できる。各メソッドには findXXX という名前をつける必要がある。XXX は、一意のメソッド名の一部である。たとえば、findApplesAndOranges のような名前をつける
  • 各検索メソッドは、エンティティ Bean のクラス定義で定義された検索メソッドの 1 つと一致する必要がある
  • その数および引数のタイプも Bean クラスの検索メソッド定義と一致する必要がある
  • 1 つのオブジェクトを検索する検索の場合、find <METHOD> メソッドの戻り値のタイプは、エンティティ Bean のローカルインタフェースのタイプと一致する必要がある。複数のオブジェクトを検索する検索では、そのコレクションと一致する必要がある
  • エンティティ Bean クラスの ejbFind メソッドの throws 句で定義されるすべての例外は、リモートホームインタフェースの、一致する find メソッドの throws 句にも含まれている必要がある
  • 検索メソッドの throws 句には、javax.ejb.FinderException を含める必要がある

findByPrimaryKey メソッド

  • すべてのローカルホームインタフェースには、常に 1 つのオブジェクトを検索する findByPrimaryKey メソッドを含める必要がある
  • このメソッドは、メソッド引数として主キークラスを宣言する必要がある
  • エンティティ Bean クラスの ejbFindByPrimaryKey メソッドの throws 句で定義されるすべての例外は、リモートホームインタフェースの、一致する find メソッドの throws 句にも含まれている必要がある
  • findByPrimaryKey メソッドの throws 句には、javax.ejb.FinderException を含める必要がある

(ローカル) home メソッド

  • create、find、remove メソッドの名前と重複しない限り、home メソッドには任意の名前をつけられる
  • エンティティ Bean クラスに指定される、一致する ejbHome メソッドは、Bean のローカルホームインタフェースに指定される home メソッドと同じ数とタイプの引数を持ち、同じタイプの戻り値を返す必要がある

リモートインタフェースの作成

リモートインタフェースで定義するビジネスメソッドのほかに、EJBObject インタフェースはいくつかの抽象的なメソッドを定義します。これらのメソッドを使うと、次の処理が可能になります。

  • Bean のホームインタフェースの取得
  • Bean のハンドルの取得 - Bean のインスタンスを一意に識別する Bean の主キーを取得するためのハンドル
  • ほかの Bean と比較して、一意かどうかの確認
  • 不要になった Bean の削除

これらの組み込みメソッドとその使用法の詳細については、『Enterprise JavaBeans Specification, v2.0』を参照してください。



『Enterprise JavaBeans Specification, v2.0』では、Bean クラスへのリモートインタフェースのメソッド実装が許可されていますが、一方で、同書で述べられているクライアント - コンテナ - EJB プロトコルに違反して、クライアントに this を介して直接参照を不用意に渡さないようにするために、この方法を行わないように勧めています。



  • エンティティ Bean のリモートインタフェースは、Bean のメソッドへのユーザーのアクセスを定義する
  • インタフェースは javax.ejb.EJBObject インタフェースを拡張する必要がある
  • リモートインタフェースに定義されるメソッドは、RMI/IIOP のルールに従う必要がある
  • つまり、引数と戻り値が正しいタイプの RMI-IIOP で、throws 句が java.rmi.RemoteException を含んでいる必要がある
  • リモートインタフェースに定義された各メソッドについて、エンティティ Bean のクラス内に一致するメソッドがある必要がある。一致するメソッドは、同じ名前、同じ数とタイプの引数、および同じ戻り値タイプを持っている必要がある
  • Enterprise JavaBean クラスの一致するメソッドの throws 句で定義されたすべての例外は、リモートインタフェースのメソッドの throws 句で定義されている必要がある
  • リモートインタフェースのメソッドに、ローカルインタフェースのタイプ、ローカルホームインタフェースのタイプ、および持続性がコンテナによって管理されるエンティティ Beans が引数または結果として使用する管理コレクションクラスを表示させることはできない

リモートインタフェースの例

次に、リモートインタフェースの例を示します。

import javax.ejb.*;
import java.rmi.*;

public interface MyEntity
   extends EJBObject
   {
   public String getAddress() throws RemoteException;
   public void setAddress(String addr) throws RemoteException;
}

Bean クラス定義の作成 (Bean 管理による持続性)

Bean 管理による持続性を使用するエンティティ Bean の Bean クラスは、abstract ではなく public として定義する必要があります。Bean クラスは、javax.ejb.EntityBean インタフェースを実装する必要があります。次に例を示します。

import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public class MyEntityBean implements EntityBean {
   // エンティティ Bean の実装。これらのメソッドは常に取り込む
   必要があります。
   public void ejbActivate() {
   }
   public void ejbLoad() {
   }
   public void ejbPassivate() {
   }
   public void ejbRemove() {
   }
   public void ejbStore() t{
   }
   public void setEntityContext(EntityContext ctx) {
   }
   public void unsetEntityContext() {
   }
   // 他のコードは省略します。
   }

これらのメソッドに加えて、エンティティ Bean のクラスでは、1 つ以上の ejbCreate メソッドと、ejbFindByPrimaryKey 検索メソッドも定義する必要があります。オプションで、ejbCreate メソッドごとに ejbPostCreate メソッドを定義できます。また、ejbFindXXX 形式の開発者定義検索メソッドを追加することもあります。XXX は、ほかのメソッド名と重複しない連続した固有のメソッド名を示します (例 : ejbFindApplesAndOranges)。

通常、エンティティ Beans は、1 つ以上のビジネスメソッドも実装します。これらのメソッドは通常、各 Bean に対して固有であり、その特定の機能を表します。任意のビジネスメソッド名を付けることができますが、この EJB アーキテクチャで使われるメソッド名と重複しないように注意してください。ビジネスメソッドは、public として宣言する必要があります。メソッド引数および戻り値は Java RMI の正しいタイプである必要があります。throws 句は、アプリケーション固有の例外を定義し、java.rmi.RemoteException を含めることもできます。

エンティティ Bean を実装するには、次の 2 つのタイプのビジネスメソッド使用します。

  • 内部メソッド - Bean 内のほかのビジネスメソッドによって使用される。Bean の外部からアクセスされることはない
  • 外部メソッド - エンティティ Bean のリモートインタフェースによって参照される

次の各項では、エンティティ Bean のクラス定義内のさまざまなメソッドについて説明します。

ejbCreate の使用

エンティティ Bean は、1 つまたは複数の ejbCreate メソッドを実装する必要があります。クライアントが Bean を呼び出すたびに、必ずこのメソッドを 1 つ使います。次に例を示します。

public String ejbCreate(String orderId, String customerId,
   String status, double totalPrice)
   throws CreateException {
      try {
      InitialContext ic = new InitialContext();
      DataSource ds = (DataSource) ic.lookup(dbName);
      con =  ds.getConnection();
      String insertStatement =
         "insert into orders values ( ? , ? , ? , ? )";
      PreparedStatement prepStmt =
         con.prepareStatement(insertStatement);
      prepStmt.setString(1, orderId);
      prepStmt.setString(2, customerId);
      prepStmt.setDouble(3, totalPrice);
      prepStmt.setString(4, status);
      prepStmt.executeUpdate();
      prepStmt.close();
   } catch (Exception ex) {
      throw new CreateException("ejbCreate: "
         +ex.getMessage());
   }
}

public String ejbPostCreate(String orderId, String customerId,String
status, double totalPrice)
   throws CreateException

{
......
......
}

ejbCreate メソッドは public として宣言し、主キーのタイプを返し、ejbCreate という名前を付ける必要があります。戻り値タイプは、キーとして使う番号に変換する正しい Java RMI タイプであれば何でもかまいません。すべての引数は、正しいタイプの Java RMI である必要があります。throws 句は、アプリケーション固有の例外を定義し、java.ejb.CreateException を含めることもできます。

このメソッドでは、関係を確立します。各 ejbCreate メソッドに対応させて、作成後すぐにエンティティサービスを処理する ejbPostCreate メソッドをエンティティ Bean のクラスで定義することができます。各 ejbPostCreate メソッドは public として宣言し、void を返し、ejbPostCreate という名前を付ける必要があります。メソッド引数がある場合は、対応する ejbCreate メソッドの数および引数タイプと一致させる必要があります。throws 句は、アプリケーション固有の例外を定義し、java.ejb.CreateException を含めることもできます。

ejbActivate と ejbPassivate の使用

サーバーアプリケーションでエンティティ Bean のインスタンスが必要になると、Bean のコンテナは、ejbActivate を起動して Bean インスタンスを使用可能な状態にします。同様に、インスタンスが不要になると、Bean のコンテナは ejbPassivate を起動して、その Bean とアプリケーションの関連付けを解除します。

Bean が最初にアプリケーションで動作可能になったとき、または Bean が不要になったときに、特定のアプリケーションタスクを実行する必要がある場合は、ejbActivate および ejbPassivate メソッド内でその操作をプログラミングします。たとえば、ejbPassivate の実行時にデータベースとバックエンドリソースへの参照を解放し、ejbActivate の実行時にそれを復元することができます。

ejbLoad と ejbStore の使用

エンティティ Bean は同期をとるために、コンテナを使ってデータベースに Bean の状態情報を格納できます。持続性が Bean によって管理されている場合は、ejbLoad および ejbStore をコーディングする必要があります。コンテナは、トランザクションの開始時に ejbLoad を呼び出し、トランザクションが無事に終了した時点で ejbStore を呼び出すことで、Bean の状態とデータベースを同期させます。

ejbStore を実装するとデータベースに状態情報が保存され、ejbLoad を実装するとデータベースから状態情報が取り出されます。

次の例は、アクティブデータの格納と取得を行う ejbLoad メソッドと ejbStore メソッドの定義を示します。

public void ejbLoad()
       throws java.rmi.RemoteException
{
   String itemId;
   javax.sql.Connection dc = null;
   java.sql.Statement stmt = null;
   java.sql.ResultSet rs = null;

   itemId = (String) m_ctx.getPrimaryKey();

   System.out.println("myBean:Loading state for item " + itemId);

   String query =
       "SELECT s.totalSold, s.quantity " +
       " FROM Item s " +
       " WHERE s.item_id = " + itemId;

   dc = new DatabaseConnection();
   dc.createConnection(DatabaseConnection.GLOBALTX);
   stmt = dc.createStatement();
   rs = stmt.executeQuery(query);

   if (rs != null) {
       rs.next();
       m_totalSold = rs.getInt(1);
       m_quantity = rs.getInt(2);
   }
}

public void ejbStore()
       throws java.rmi.RemoteException
{
   String itemId;
   itemId = (String) m_ctx.getPrimaryKey();
   DatabaseConnection dc = null;
   java.sql.Statement stmt1 = null;
   java.sql.Statement stmt2 = null;

   System.out.println("myBean:Saving state for item " + itemId);

   String upd1 =
       "UPDATE Item " +
       " SET quantity = " + m_quantity +
       " WHERE .item_id = " + itemId;

   String upd2 =
       "UPDATE Item " +
       " SET totalSold = " + m_totalSold +
       " WHERE .item_id = " + itemId;

   dc = new DatabaseConnection();
   dc.createConnection(DatabaseConnection.GLOBALTX);
   stmt1 = dc.createStatement();
   stmt1.executeUpdate(upd1);
   stmt1.close();
   stmt2 = dc.createStatement();

   stmt2.executeUpdate(upd2);
   stmt2.close();
}

ほかの Bean と同時にトランザクションにアクセスする Bean の遮断レベルの詳細については、を参照してください。

setEntityContext と unsetEntityContext の使用

コンテナは、エンティティ Bean のインスタンスを作成してコンテナへの Bean のインタフェースを提供してから、setEntityContext を呼び出します。コンテナから渡されるエンティティのコンテキストを格納するには、このメソッドを実装します。後からこの参照を使って、インスタンスの主キーなどを取得することができます。

   public void setEntityContext(javax.ejb.EntityContext ctx)
   {
   m_ctx = ctx;
   }

同様に、コンテナは unsetEntityContext を呼び出して、インスタンスからコンテナ参照を削除します。これは、Bean のインスタンスが削除の対象となる前にコンテナが呼び出す最後の Bean クラスメソッドです。この呼び出しのあと、Java ガベージコレクションメカニズムは最終的にそのインスタンスに対して finalize を呼び出し、そのインスタンスをクリーンアップして廃棄します。

   public void unsetEntityContext()
   {
   m_ctx = null;
   }

ejbRemove の使用

クライアントは、エンティティ Bean のホームインタフェースまたはコンポーネントインスタンスで remove メソッドを呼び出して、データベースから関連するレコードを削除できます。クライアントがエンティティ Bean のホームインタフェースまたはコンポーネントインタフェースで remove メソッドを呼び出した場合、またはカスケード削除処理が行われた場合は、それに対応してコンテナがエンティティ Bean のインスタンスで ejbRemove メソッドを呼び出します。

検索メソッドの使用

エンティティ Beans は持続的でであり、複数のクライアント間で共有され、一度に複数回インスタンス化される可能性があります。したがって、エンティティ Bean は少なくとも 1 つの ejbFindByPrimaryKey メソッドを実装する必要があります。このメソッドによって、クライアントとコンテナは特定の Bean インスタンスを検出することができます。すべてのエンティティ Beans は、識別シグネチャとして固有の主キーを提供する必要があります。ejbFindByPrimaryKey メソッドを Bean のクラスに実装して、Bean がその主キーをコンテナに返すことができるようにします。

次の例は、FindByPrimaryKey の定義を示します。

public String ejbFindByPrimaryKey(String key)
       throws java.rmi.RemoteException,
          javax.ejb.FinderException

特定のエンティティ Bean のインスタンスを、その Enterprise JavaBean の動作内容、そのインスタンスが操作する値などの条件に基づいて検索する場合があります。特定の実装に関するこれらの検索メソッドの名前は ejbFindXXX の形式です。XXX は、ほかのメソッド名と重複しない連続した固有のメソッド名を表します (例 : ejbFindApplesAndOranges)。

検索メソッドは public として宣言され、その引数および戻り値は正しいタイプの Java RMI である必要があります。各検索メソッドの戻り値のタイプは、エンティティ Bean の主キーのタイプか、同じ主キータイプのオブジェクトのコレクションである必要があります。戻り値のタイプがコレクションのとき、次のいずれかである必要があります。

  • JDK 1.1 の java.util.Enumeration インタフェース
  • Java 2 の java.util.Collection インタフェース

検索メソッドの throws 句は、アプリケーション固有の例外であり、java.rmi.RemoteException または java.ejb.FinderException、あるいはその両方を含めることができます。

読み取り専用 Beans の使用

読み取り専用 Bean は、EJB クライアントが変更できないエンティティ Bean です。ただし、読み取り専用 Bean が表すデータは、ほかの Enterprise JavaBean や、データベースの直接更新などの方法によって、外部から更新される場合があります。



Sun ONE Application Server の今回のリリースでは、Bean 管理による持続性を使用するエンティティ Beans のみを読み取り専用として指定できます。

読み取り専用 Beans は Sun ONE Application Server に固有のもので、Enterprise JavaBeans Specification, v2.0 には規定されていません。



この節では、次の項目について説明します。

読み取り専用 Bean の特性とライフサイクル

読み取り専用 Bean は、基になるデータがまったく変更されないか、まれにしか変更されない場合に最も適しています。たとえば、外部で更新される特定企業の株式相場を表す場合に読み取り専用 Bean を使用できます。その場合、通常のエンティティ Bean を使用すると ejbStore呼び出しの負荷が発生する可能性がありますが、読み取り専用 Bean を使用すると、これを避けることができます。

読み取り専用 Beans には次の特性があります。

  • エンティティ Beans のみを読み取り専用 Beans にすることができる
  • Bean 管理による持続性のみを使用できる
  • コンテナ管理トランザクションのみを使用できる。読み取り専用 Beans は、独自のトランザクションを開始できない
  • 読み取り専用 Beans は Bean の状態を更新しない
  • ejbStore はコンテナによって呼び出されない
  • ejbLoad は、トランザクションメソッドが呼び出されたとき、Bean が最初にキャッシュ内に作成されたとき、または Bean の refresh-period-in-seconds によって制御される一定間隔でのみ呼び出される
  • ホームインタフェースには、find メソッドをいくつでも設定できる。find メソッドの戻り値タイプは、同じ Bean タイプの主キー (または主キーのコレクション) にする必要がある
  • Bean が表すデータが変更される可能性がある場合は、refresh-period-in-seconds を設定して、一定間隔でその Bean を更新する必要がある。この一定間隔で、ejbLoad が呼び出される

読み取り専用 Bean は、適切な find メソッドを使って作成されます。

読み取り専用 Bean はキャッシュされ、エンティティ Beans と同じキャッシュプロパティを持ちます。キャッシュのスペースを空けるための削除候補として読み取り専用 Bean が選択されると、ejbPassivate が呼び出され、その Bean は空きプールに戻されます。空きプールにある Bean は ID を持たず、検索リクエストの処理にのみ使用されます。

読み取り専用 Bean は、通常の読み取り/書き込みエンティティ Beans と同様にネーミングサービスに結合されるので、クライアントは、読み取り/書き込みエンティティ Beans を検索する場合と同じ方法で読み取り専用 Bean を検索できます。

読み取り専用 Bean の開発に関する注意

  • ホームインタフェースでは、create または remove メソッドを含めない
  • メソッドのトランザクション属性には、有効な EJB 2.0 トランザクション属性を使用する
  • TX_SUPPORTED を含める理由は、同じトランザクションでコミットされないデータを読み取るためです。また、TX 属性を使用して ejbLoad を強制することもできます。

読み取り専用 Bean の更新

読み取り専用 Bean を更新するには、次に示すようにいくつかの方法があります。

トランザクションメソッドの起動

トランザクションメソッドを起動することによって、ejbLoad を起動します。

定期的な更新

Sun ONE Application Server 固有の XML ファイルで refresh-period-in-seconds 要素を指定すると、読み取り専用 Bean を定期的に更新できます。

  • refresh-period-in-seconds にゼロを指定すると、その Bean は (トランザクションメソッドにアクセスするまで) 更新されない
  • 1 以上の値を指定すると、その Bean は、指定した間隔で更新される


  • Sun ONE Application Server の外部でデータ変更される可能性がある場合は、これが Bean の状態を更新する唯一の方法です。



プログラムによる更新

一般に、読み取り専用 Bean によってキャッシュされたデータを更新する Bean では、その状態を更新するように読み取り専用 Bean に知らせる必要があります。ReadOnlyBeanNotifier を使用すると、読み取り専用 Beans を強制的に更新することができます。これを行うには、ReadOnlyBeanNotifier Bean で次のメソッドを起動します。

   public interface ReadOnlyBeanNotifier
      extends java.rmi.Remote
   {
      refresh(Object PrimaryKey)
         throws RemoteException;
   }

ReadOnlyBeanNotifier のインタフェースは、コンテナによって実装されます。ユーザーは、次のコードを使って ReadOnlyBeanNotifier を検索できます。

com.sun.ejb.ReadOnlyBeanNotifier notifier = com.sun.ejb.containers.ReadOnlyBeanHelper.getReadOnlyBeanNotifier
   (<ejb-name-of -the-target>);
   notifier.refresh(<PrimaryKey>);

読み取り専用 Beans によってキャッシュされたデータを更新する Beans では、refresh メソッドを呼び出す必要があります。その読み取り専用 Bean に対する次回の (トランザクションでない) 呼び出しでは、ejbLoad が起動します。

読み取り専用 Bean の配備

読み取り専用 Beans は、ほかのエンティティ Beans と同じ方法で配備されます。ただし、Sun ONE Application Server 固有の XML ファイル内の Bean のエントリでは、is-read-only-bean 要素を true に設定する必要があります。つまり、次のように設定します。

<is-read-only-bean>true</is-read-only-bean>

また、refresh-period-in-seconds 要素に値を設定して、Bean が更新される間隔を指定することもできます。この要素が存在しない場合は、デフォルトの 600 (秒) とみなされます。

同じトランザクションコンテキストを持つ要求はすべて、同じ 読み取り専用 Bean インスタンスに転送されます。配備するときに、allow-concurrent-access 要素を true (同時アクセスを可能にする)、または false (同じ読み取り専用 Bean への同時アクセスを直列化する) に設定することによって、複数の要求を直列化する必要があるかどうかを指定できます。デフォルトは false です。

これらの要素に関する詳細は、『Sun ONE Application Server 管理者用設定ファイルリファレンス』を参照してください。

同時アクセスの同期化処理

エンティティ Bean の開発者は、通常は、複数のトランザクションからのエンティティ Bean への同時アクセスについて考慮する必要はありません。このような場合、Bean のコンテナは自動的に同期をとります。Sun ONE Application Server では、コンテナは、Bean を使う同時発生トランザクションごとに 1 つのエンティティ Bean インスタンスを活性化します。

トランザクション同期は、データベースアクセス呼び出し時に基礎となっているデータベースによって自動的に実行されます。通常は、基礎となっているデータベースやリソースと連携して同期をとります。その方法の 1 つは、たとえば適切な遮断レベルを選択したり、select for update 句を使用したり、ejbLoad メソッド内で対応するデータベースをロックすることです。その特性は、使用しているデータベースによって異なります。

詳細は、『Enterprise JavaBeans Specification, v2.0』の同時アクセスに関連する箇所を参照してください。


前へ      目次      索引      次へ     
Copyright 2002 Sun Microsystems, Inc. All rights reserved.