5.5.2 コンテナ管理のEntityManagerを使用する場合の永続化コンテキスト
コンテナ管理のEntityManagerを使用する場合,永続化コンテキストのライフサイクルはコンテナによって管理され,JTAトランザクションとともに自動的に伝播されます。永続化コンテキストのライフサイクルの種類として,トランザクションスコープの永続化コンテキスト,または拡張された永続化コンテキストを選択できます。
それぞれの永続化コンテキストについて説明します。
(1) トランザクションスコープの永続化コンテキスト
JPA仕様では,トランザクションと同じライフサイクルの永続化コンテキストのことをトランザクションスコープの永続化コンテキストといいます。
EntityManagerのライフサイクルは,デフォルトでトランザクションのライフサイクルと同じです。このため,EntityManagerが持つ永続化コンテキストにキャッシュされた更新は,トランザクションがコミットするときにデータベースに反映されます。
(a) 永続化コンテキストのライフサイクル
トランザクションスコープの永続化コンテキストのライフサイクルを次に説明します。
-
永続化コンテキストの作成
トランザクションスコープの永続化コンテキストは,コンテナ管理のEntityManagerが,JTAトランザクションの中で初めて呼び出されたときに作成されます。
作成された永続化コンテキストはJTAトランザクションに関連づけられます。
その後,同じJTAトランザクションの中でコンテナ管理のEntityManagerを使用した場合には,この永続化コンテキストが使用されます。
-
永続化コンテキストの破棄
JTAトランザクションがコミットまたはロールバックするときに,トランザクションスコープの永続化コンテキストは破棄されます。
コンテナ管理のEntityManagerがトランザクションの外で呼び出された場合には,EntityManagerのメソッド呼び出しが終了した時点で,データベースからロードされたすべてのエンティティは即座にdetached状態となります。
(2) 拡張された永続化コンテキスト
Java EE環境では,Stateful Session BeanからEntityManagerを使用する場合には,永続化コンテキストの生存期間をStateful Session Beanの生存期間と同じにできます。この場合,更新はトランザクションがコミットするたびにデータベースに反映されますが,永続化コンテキスト内で管理されているエンティティオブジェクトは,複数のトランザクションにわたってmanaged状態のまま保持されます。Stateful Session Beanと同じライフサイクルの永続化コンテキストのことを,JPAでは拡張永続化コンテキストと呼びます。
拡張された永続化コンテキストは,Stateful Session Beanが作成されるのと同時に作成され,そのStateful Session Beanに関連づけされます。その後,Stateful Session Beanが破棄されるのと同時に破棄されます。
Stateful Session Beanが別のStateful Session Beanを作成する場合で,作成する側と作成される側が共に拡張永続化コンテキストを使用するように定義されている場合には,作成する側の永続化コンテキストが,作成される側に引き継がれます。この引き継ぎは,Stateful Session Beanを作成する時点でトランザクションがアクティブであるかどうかにかかわらず実施されます。Stateful Session Beanの作成時に永続化コンテキストの引き継ぎが行われた場合には,その永続化コンテキストを共有するすべてのStateful Session Beanが破棄されるときに,永続化コンテキストも破棄されます。
(3) 拡張された永続化コンテキストとトランザクション
拡張された永続化コンテキストは,EntityManagerのインスタンスが作成されたときからクローズされるまで存在します。複数のトランザクションとEntityManagerのトランザクション外の呼び出しに対応しています。
トランザクションとの関連を次に示します。
-
EntityManagerがトランザクションの範囲内で呼び出されるか,永続化コンテキストがバインドしているstateful session beanがトランザクションのスコープで呼び出されると,EntityManagerで管理されたエンティティがトランザクションに参加します。
-
トランザクションが実行中かどうかにかかわらず,persist,remove,merge,refresh操作が行われることがあります。この場合,EntityManagerがトランザクションに参加して,トランザクションがコミットするときにデータベースに反映されます。
-
トランザクションがコミットされたあとでも,エンティティオブジェクトへの参照は保持されます。エンティティオブジェクトはEntityManagerに管理され,トランザクション間では,管理されているオブジェクト(managed状態のエンティティ)として更新されます。
(4) 永続化コンテキストの伝播
コンテナ管理のEntityManagerを使用する場合,永続化コンテキストはJTAトランザクションによって伝播され,複数のEntityManagerと関連づくことがあります。ただし,永続化コンテキストが伝播するのは,同じアプリケーションサーバ内だけです。リモートのアプリケーションサーバに永続化コンテキストが伝播されることはありません。
次に,永続化コンテキストの伝播についてコンポーネントが呼び出されたときの状態ごとに説明します。
- コンポーネントが呼び出されたときに,JTAトランザクションが存在しないか,またはJTAトランザクションに永続化コンテキストが関連づいていない場合
-
永続化コンテキストは伝播されません。このコンポーネントからEntityManagerが呼び出したときの動作は,次のようになります。
-
トランザクションスコープの永続化コンテキストを使用するEntityManagerが呼び出された場合には,新しい永続化コンテキストが作成されます。
-
拡張永続化コンテキストを使用するEntityManagerが呼び出された場合には,呼び出されたStateful Session Beanに関連づいている拡張永続化コンテキストが使用されます。
-
EntityManagerが呼び出されたときに,JTAトランザクションが存在する場合には,JTAトランザクションに永続化コンテキストを関連づけます。
-
- コンポーネントが呼び出されたときに,JTAトランザクションが伝播され,JTAトランザクションに永続化コンテキストが関連づいている場合
-
このコンポーネントからEntityManagerを呼び出したときの動作は次のようになります。
-
コンポーネントがすでに拡張永続化コンテキストを持っているStateful Session Beanにもかかわらず,JTAトランザクションに別の永続化コンテキストが関連づいている場合は,コンテナによってEJBExceptionがスローされます。
-
トランザクションスコープの永続化コンテキストを使用するEntityManagerが呼び出された場合,伝播してきたJTAトランザクションに関連づいている永続化コンテキストが使用されます。
-