この章ではエンティティBeanの一般的な概念と、特にコンテナ管理の永続性を持つエンティティBeanについて説明します。
この章の内容は次のとおりです。
J2EE SDK環境内において、エンティティBeanはリレーショナル・データベースのビジネス・オブジェクトを表します。通常、エンティティBeanはリレーショナル・データベースに基底の表を持ち、Beanの各インスタンスはそのデータベース内の行に対応します。
エンティティBeanには次のような特徴があります。
永続性があります。
共有アクセスが可能です。
主キーを保持します。
他のエンティティBeanと関連する場合があります。
エンティティBeanの詳細は次のドキュメントを参照してください。
『The J2EE Tutorial』: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/EJBConcepts4.html#62950
EJB 2.0仕様: http://java.sun.com/products/ejb/docs.html
この項では、コンテナ管理の永続性を持つエンティティBeanに関する次のトピックについて説明します。
用語的には、コンテナ管理の永続性とはエンティティBeanに必要なデータベース・アクセスを処理するEJBコンテナのプロセスのことです。つまり、BeanのコードにはSQLコールは含まれません。これによって、Beanのコードが基底データベースで不可視になります。Beanのデータの永続性を管理するためのいくつかのコールバック・メソッド(「コールバック・メソッド」を参照)は実装の必要がありません。これは、コンテナによってデータベースに対する永続データの格納およびリロードが行われるためです。また、コンテナではBeanに対する主キーも提供されるため、主キーの管理を用意する必要はありません(「主キーの構成」を参照)。
コンテナ管理の永続性を持つOrionエンティティBeanでは、エンティティBeanからデータベースへのデータを永続させるため、EJBコンテナでOrion永続性マネージャが使用されます。用語の詳細は「はじめに」を参照してください。
永続性マネージャの詳細は次のトピックを参照してください。
エンティティBeanのデプロイメント・ディスクリプタには、Beanの永続フィールド(「コンテナ管理の永続フィールド」を参照)および関連(「コンテナ管理の関連」を参照)を定義する抽象スキーマが含まれます。
注意: 抽象スキーマと物理スキーマという用語を混同しないでください。リレーショナル・データベースでは、物理スキーマは表および列で構成されますが、抽象スキーマは、データ・アクセス・コールの生成にコンテナで必要とされる情報のプロバイダとなります。 |
この項の内容は次のとおりです。
エンティティBeanの永続フィールドはBeanの状態を定義します。これらのフィールドは基底となるデータベースに格納されます。コンテナは実行時に、Beanの状態とデータベースとの自動同期を実行します。デプロイ時に、コンテナは通常、表の列にマップされた永続フィールドでエンティティBeanをデータベース表にマップします。
永続フィールドはコンテナ管理の永続性では仮想的です。つまり、ユーザーはこのフィールドを抽象スキーマで宣言しますが、エンティティBeanクラスのインスタンス変数とはしません。ただし、ユーザーは永続フィールドに対するgetterおよびsetterをコードで次のように提供します。
public abstract String getEmployeeName() throws RemoteException public abstract String getAddress() throws RemoteException public abstract void setAddress(String newAddress) throws RemoteException
コンテナはこれらのメソッドの実装を提供します。
前述した例では、対応する永続フィールドはemployeeName
とaddress
です。
ejb-jar.xml
ファイル形式のEJBデプロイメント・ディスクリプタが、これらのフィールドを永続的であると宣言します。各フィールド名は、デプロイメント・ディスクリプタの<cmp-field><field-name>
要素で次のように定義する必要があります。
<entity> ... <cmp-field><field-name>employeeName</cmp-field></field-name> <cmp-field><field-name>address</cmp-field></field-name> ... </entity>
永続フィールドの構成の詳細は、「コンテナ管理の永続フィールドの構成」を参照してください。
エンティティBeanの実装の詳細は、「コンテナ管理の永続性を持つEJB 2.0エンティティBeanの実装」を参照してください。
エンティティBeanは他のエンティティBeanと関連する場合があります。このエンティティBeanの動作は、リレーショナル・データベースの表の動作と似ています。
EJBコンテナは、コンテナ管理の永続性を持つエンティティBeanにおける関連を制御します。
OC4Jは次のようなコンテナ管理の関連(CMR)タイプをサポートしています。
1対1: エンティティBeanのインスタンスが他のエンティティBeanのインスタンスと関連します。たとえば、それぞれの車に1人の運転手が乗っているレーシング・トラックの仮想モデルでは、CarEJB
とDriverEJB
が1対1関連にあります。
1対多: エンティティBeanのインスタンスが他のエンティティBeanの複数のインスタンスと関連します。前述したレーシング・トラックの例を再び利用すると、レーシング・トラックで複数の車が競争できる場合に、RacingTrackEJB
がCarEJB
に対して1対多関連にあります。
多対1: エンティティBeanの複数のインスタンスが他のエンティティBeanの1つのインスタンスと関連します。たとえば、1対多のレーシング・トラックの例を逆の視点から見ると、多数の車が1つのレーシング・トラックで競争しているため、CarEJB
がRacingTrackEJB
に対して多対1関連にあります。
多対多: エンティティBeanのインスタンスが互いに複数のインスタンスと関連します。たとえば、レーシング・トラックではそれぞれの車が複数の整備士によって整備され、すべての整備士は複数の車を整備します。このことからCarEJB
とMechanicEJB
は多対多関連にあります。
エンティティBeanはローカルBeanオブジェクトによって関連の「1」側を表しますが、「多」側はJavaのCollection
を使用して表されます。
これらのエンティティBean関連の参照整合性を維持するのは、EJBコンテナです。
詳細は次のトピックを参照してください。
CMRの方向概念では、関連は双方向または単方向のどちらかになります。双方向の関連では、各エンティティBeanが他のBeanを参照する関連フィールドを持ちます。関連フィールド(「関連フィールド」を参照)を介して、エンティティBeanのコードはその関連オブジェクトにアクセスできます。単方向の関連では、1つのエンティティBeanのみが他のBeanを参照する関連フィールドを持ちます。
EJB QL問合せ(「EJB QLの理解」を参照)は関連全体をナビゲートできます。関連の方向によって、問合せがあるBeanから別のBeanにナビゲートできるかどうかが決まります。
関連フィールドは関連するBeanを特定します。関連フィールドはデータベース表における外部キーと同様に機能します。
永続フィールド(「コンテナ管理の永続フィールド」を参照)と同様に、関連フィールドは仮想的であり、アクセス・メソッドを持つエンタープライズBeanクラスで定義されます。ただし、永続フィールドとは逆に、関連フィールドはBeanの状態は表しません。
関連フィールドの詳細は、「コンテナ管理の関連フィールドの構成」を参照してください。
コンテナ管理の永続性を持つエンティティBeanのライフ・サイクルを有効にするため、実装が必要なコールバック・メソッドが多数あります。これらのメソッドのいくつかはjavax.ejb.EntityBean
インタフェースで定義されますが、その他(ejbCreate
とejbPostCreate
)の実装はEJB 2.0仕様で義務付けられています。
コンテナは指定された時刻にコールバック・メソッドを起動します。これらのメソッドにはロジックを追加する場合としない場合があります。
次の表に各メソッドの詳細と、エンティティBeanクラスのコールバック・メソッドに対する実装要件を一覧表示します。
ユーザーは、エンティティBeanのfinderメソッド(「finderメソッドの理解」を参照)またはselectメソッド(「selectメソッドの理解」を参照)を使用して、エンティティBeanのインスタンスに対して問合せを行います。
選択基準は適切な問合せ構文を使用して表します(「問合せ構文の理解」を参照)。
この項の内容は次のとおりです。
EJB問合せ言語(EJB QL)は、移植性があり最適化可能な形式によるfinderメソッドおよびselectメソッドのセマンティクスの定義に使用される仕様言語です。Orion永続性マネージャはEJB QLの自動コンパイルを実行できます。ユーザーは、エンティティBeanのデプロイメント・ディスクリプタでEJB QL問合せを定義します。
EJB QLを使用すると次のような利点があります。
データベース構造(表やフィールドなど)を知る必要がありません。
データベースの表およびフィールドを使用するかわりに、エンティティBeanの属性を使用して問合せを構成できます。
問合せの関連を使用して、属性から属性へのナビゲーションを提供できます。
EJB QLの問合せは、データベースに依存していないため、移植性があります。
参照クラスをSELECT
句で指定できます。
EJB QLの問合せの難点は、複合問合せを構成する際に使用することが難しい点です。
EJB QLには次のような制限があります。
コメントは使用できません。
日付および時間の値の単位はミリ秒で、Java long
を使用します。日付または時間のリテラルは整数リテラルとする必要があります。ミリ秒の値を生成するには、java.util.Calendar
クラスを使用します。
EJB 2.0のコンテナ管理の永続性では継承がサポートされていません。このため、型が異なる2つのエンティティBeanは比較できません。
ユーザーは、EJB QL(「EJB QLの理解」を参照)またはネイティブSQLを使用して、基底となるリレーショナル・データベースに対するエンティティBean問合せを表すことができます。
移植性があり最適化可能なEJB QLの方がより推奨されます。
EJB QL問合せにはSELECT
、FROM
およびWHERE
という3つの句があります。SELECT
およびFROM
句は必須ですが、WHERE
句はオプションです。EJB QL問合せのハイレベル構文を次に示します。
EJB QL ::= select_clause from_clause [where_clause]
SELECT
句は問合せで返されるオブジェクトまたは値の型を定義します。戻り型はローカル・インタフェース、リモート・インタフェースまたは永続フィールドのいずれかになります。
FROM
句は、SELECT
およびWHERE
句で参照される場合がある、1つ以上の識別変数を宣言することで問合せの有効範囲を定義します。識別変数は次の要素のいずれかを表します。
エンティティBeanの抽象スキーマ名
1対多関連における「多」側である集合のメンバー
WHERE
句は問合せで取得されるオブジェクトまたは値を制限する条件式です。オプションではありますが、ほとんどの問合せにはWHERE
句があります。
EJB QL構文の詳細は、http://java.sun.com/products/ejb/docs.html
でEJB 2.0仕様を参照してください。
EJB QL問合せ構文を次の例で示します。たとえば、エンティティBeanのホーム・インタフェースでfindByZipCode
メソッドを宣言して、特定のジップ・コードを持つEmployee
Beanをすべて取得します。
public Collection findByZipCode(String zipCode) throws RemoteException, CreateException
これはデプロイメント・ディスクリプタの次のEJB QL文を使用して表されます。
FROM contactInfo WHERE contactInfo.zip = ?1
このEJB QL文は「zipCode
引数に等しいジップ・コードを持つEmployee
Beanをすべて選択」するという意味です。選択するものを示すSELECT
句は、finderメソッドのEJB QL文では必要ありません。これは、finderメソッドがそのBeanタイプのリモート参照を常に選択するためです。
ネイティブSQLは、EJB QLがサポートしていない基底リレーショナル・データベースの詳細な問合せ機能を利用する場合に適しています。
EJB QLはfinderメソッド(「finderメソッドの理解」を参照)とselectメソッド(「selectメソッドの理解」を参照)で使用できます。ネイティブSQLを使用するには直接JDBCコールを使用する必要があります。
EJBファインダはEJB 2.0仕様で定義されている問合せです。EJBファインダはエンティティBean参照を取得します(および返します)が、問合せはJavaオブジェクトを返します。
ファインダには検索基準を定義するfinderメソッド(ejbFind
)が含まれます。
findByPrimaryKey
finderメソッドは常に両方のホーム・インタフェース(ローカルとリモート)で定義され、主キーを使用してこのBeanに対するエンティティ参照を取得します。一方または両方のホーム・インタフェースで他のfinderメソッドを定義して、1つまたは複数のエンティティBean参照を取得できます。
注意: finderメソッドはクライアントに公開されます。 |
finderメソッドの定義および実装の詳細は、「EJB QLのfinderメソッドの実装」を参照してください。
selectメソッド(ejbSelect
)は、主にコンテナ管理の永続フィールド(「コンテナ管理の永続フィールド」を参照)または関連フィールド(「関連フィールド」を参照)の値を返すために使用されます。すべての値は固有のオブジェクト型で返されます。プリミティブ型はすべて、同様の関数を持つオブジェクトでラッピングされます(たとえば、int
プリミティブ型はInteger
オブジェクトでラッピングされます)。ejbSelect
メソッドは、エンティティBeanインスタンス内の内部使用を目的にした問合せメソッドです。抽象Beanで指定されるため、ejbSelect
メソッドはホームまたはコンポーネント・インタフェースでクライアントに直接公開されません。抽象的に定義することで、それぞれのBeanにこのようなメソッドをゼロ以上含むことができます。
selectメソッドには次のような特徴があります。
メソッド名にはejbSelect
という接頭辞が必要です。
public
として宣言する必要があります。
abstract
として宣言する必要があります。
アプリケーション固有の例外を同様に指定する場合でも、throws
句でjavax.ejb.FinderException
を指定する必要があります。
EJB 2.0では、ejb-jar.xml
ファイルのresult-type-mapping
タグによってejbSelect
メソッドの戻り型が決まります。EJBObject
を返すにはフラグをRemote
に設定し、EJBLocalObject
を返すにはフラグをLocal
に設定します。
selectメソッドの詳細は、「EJB QLのselectメソッドの実装」を参照してください。
エンティティBeanの並行性とデータベース分離レベルを使用することで、リソース競合を回避し、同時実行中に各ユーザーがデータベースへの変更をお互いに上書きすることを防止します。
この項の内容は次のとおりです。
java.sql.Connection
オブジェクトは特定のデータベースへの接続を表します。Connection
ではリソース競合からの保護を定義する4つのデータベース分離レベルが提供されます。2人以上のユーザーが同じリソースを更新しようとすると、更新の紛失が起こる場合があります。つまり、1人のユーザーが、認識しないまま他のユーザーのデータを上書きする可能性があります。
Oracleでは次の分離レベルがサポートされています。
transaction_read_committed
: 不正な読取りが防止されます。反復不可読取りと仮読取りが発生する場合があります。このレベルは、コミットされていない変更を持つ行をトランザクションが読み取ることのみを阻止します。
transaction_serializable
: 不正な読取り、反復不可読取りおよび仮読取りが防止されます。このレベルにはtransaction_repeatable_read
における禁止が含まれます。さらに、あるトランザクションがWHERE
条件を満たすすべての行を読み取り、2番目のトランザクションがWHERE
条件を満たす行を挿入し、最初のトランザクションが同じ条件について再読取りを行い、2回目の読取りで追加的な「ファントム」行を取得する、という仮想状況の発生も阻止されます。
データベース分離レベルの詳細は、「データベース分離レベルの構成」を参照してください。
OC4Jには、コンテナ管理の永続性を持つエンティティBean内のリソース競合とパラレル実行を処理するための並行性モードも用意されています。並行性モードでは、リソース競合管理のためいつ遮断するか、またはいつパラレル実行を行うかを決定します。
使用できる並行性モードの一覧を次に示します。
pessimistic: リソース競合を管理し、パラレル実行を許可しません。1人のユーザーのみが指定された時間にエンティティBeanを実行できます。
optimistic: リソース競合を監視しません。このため、データベース分離レベルで並行性を管理します。複数のユーザーがエンティティBeanをパラレルに実行できます。
read-only: コンテナはBeanの状態に対するあらゆる更新を許可しません。複数のユーザーがエンティティBeanをパラレルに実行できます。
並行性モードの詳細は、「並行性モードの構成」を参照してください。
組合せがリソース競合の結果に影響する場合は、エンティティBeanの並行性モードとデータベース分離レベルの両方を指定することができます。詳細は「エンティティBeanのデータベース分離レベルと並行性モードの組合せ」を参照してください。
データベース分離レベルの設定は、pessimistic
およびread-only
並行性モードには影響しません。分離レベルは、外部ソースがデータベースを変更している場合にのみ関係します。
committed
データベース分離レベルでoptimistic
並行性モードを選択した場合、更新が失われる可能性があります。serializable
分離レベルでoptimistic
並行性モードを選択した場合、更新が失われることはなく、データの整合性が常に保たれます。ただし、リソース競合エラーとしてORA-8177
例外を受け取る場合があります。
pessimistic
並行性モードのエンティティBeanでは、複数のクライアントによる実行は(同じ主キーの同じインスタンスまたは異なるインスタンスのどちらでも)許可されません。1回に1つのクライアントのみがインスタンスを実行できます。
optimistic
並行性モードのエンティティBeanでは、Beanの複数のインスタンスがパラレルに実行できます。これによって、2つの異なるトランザクションが同じ行を同時に更新する場合があるため、更新の紛失(および競合)が起こる可能性があります。
トランザクション分離レベルをserializable
に設定すると、競合が発生した場合の検知が可能になります。現在、トランザクションの1つの更新でSQLException
が発生した場合、このトランザクションはロールバックされます。
オプションで、<entity-deployment>
要素のtx-retries
属性を1よりも大きい値に設定すると、トランザクションの再試行が行われます。<entity-deployment>
要素およびその属性の詳細は、表A-1「<entity-deployment>要素の属性」を参照してください。
すべての並行性モードは、独立環境またはクラスタリング環境のどちらで使用される場合でも同じように動作します。これは、並行性モードがデータベース・レベルでロックされているためです。このため、pessimistic Beanインスタンスがノード間でクラスタリングされている場合でも、1つのインスタンスが実行を試行すると、データベースはその他すべてのインスタンスをロックします。
詳細は次のトピックを参照してください。
『Oracle Containers for J2EE構成および管理ガイド』の「クラスタリングの概要」
『Oracle Containers for J2EE構成および管理ガイド』の「OC4Jでのアプリケーションのクラスタリング」
『Oracle Application Server高可用性ガイド』のアクティブ/アクティブ・トポロジにおけるOracle Application Server Cluster(OC4J)に関する項
次のような状況の場合に、コンテナ管理の永続性を持つエンティティBeanを使用することをお薦めします。
Beanがプロシージャではなくビジネス・エンティティを表す場合。
Beanの状態が永続的である場合。Beanインスタンスが終了、またはJ2EEサーバーが停止した場合でも、Beanの状態はデータベースにそのまま存在します。
使用するEJBコンテナがサービスの持続をOrion永続性マネージャに委譲する場合。