[解決済み] JPA Entity Managerは閉鎖されるべきか?
質問
以下のようなメソッドを持っています。
public Profile readUser(String email){
EntityManager em = EMF.get().createEntityManager();
return em.find(Profile.class, email);
}
エンティティマネージャーの使い方は上記の通りでよいのでしょうか?それとも、閉じる必要があるのでしょうか?
どのように解決するのですか?
答えはこうでしょう。 それは依存します。 .
エンティティマネージャは、エンティティが存在するコンテキストにアクセスするための鍵です。もしあなたのアプリケーションが日本証券業協会のアプリケーションであれば、コンテキストの寿命がどれくらいかを考慮しなければなりません。
ユーザーのリクエストごとにエンティティマネージャーを作成することを考えましょう。そこで、あるリクエストに対応している間は、エンティティマネージャーを開いたままにしておき、それが終わったら閉じます。
日本証券業協会のアプリケーションでは、アプリケーションの全期間中(大量のデータを扱わないと仮定して)エンティティ・マネージャーを開いておき、アプリケーションがシャットダウンしたときに閉じることを考えたかもしれません。
結論として、いつ開き、いつ閉じるかは、あなたの戦略と設計に完全に依存します。そのコンテキストでエンティティをもはや必要としないとき、それを閉じます。
あなたの例では、それは明らかではありませんが、メソッド内でEMを作成しているので、戻る前にそれを閉じるべきです。そうでなければ、もはやそれに再びアクセスすることはできません(コードでは明らかではありませんが、何らかのレジストリにそれを保持していない限り)。
もしクローズしなければ、エンティティは使い終わった後でもアタッチされたままです。コンテキストは、EM にもはやアクセスできないときでも、生き続けます。
その JPA仕様 にはより詳細な情報が含まれています。セクション中の 7.7 アプリケーションが管理する永続性コンテクスト と書いてあります。
アプリケーションで管理されるエンティティ・マネージャが使用される場合、アプリケーションは 永続化プロバイダのエンティティ・マネージャと直接対話します。 ファクトリーと直接対話し、エンティティ・マネージャーのライフサイクルを管理し、永続化コンテキストを取得および破棄します。 永続化コンテキストを破棄します。
このようなアプリケーションで管理される永続性コンテキストはすべて、スコープが拡張され スコープで拡張され、複数のトランザクションにまたがることができます。
は
EntityManagerFactory.createEntityManager
メソッドとEntityManager
close
そしてisOpen
メソッドを使用します。 メソッドは、アプリケーションで管理されるエンティティ・マネージャとそれに関連する のライフサイクルを管理するために使用されます。拡張された永続性コンテキストは を使用してエンティティ・マネージャが作成された時点から存在します。
EntityManagerFactory.createEntityManager
を使って作成された時点から、エンティティ・マネージャが によって閉じられるまで存在します。EntityManager.close
.アプリケーションによって管理されるエンティティ・マネージャから取得される拡張永続性コンテキストは、独立した永続性コンテキストです。 エンティティマネージャから取得した拡張永続化コンテキストは、スタンドアロン永続化コンテキストであり、トランザクションと共に伝搬されません。 トランザクションと一緒に伝搬されません。
[...] アプリケーションが管理する
EntityManager.close
メソッドはエンティティ・マネージャーを閉じて その永続性コンテキストと他のリソースを解放します。closeを呼び出した後 を呼び出した後、アプリケーションはそれ以上EntityManager
インスタンスに対してそれ以上メソッドを呼び出してはいけません。getTransaction
とisOpen
または はIllegalStateException
が投げられます。トランザクションがアクティブなときにcloseメソッドが呼び出された場合 メソッドが呼び出された場合、トランザクションが完了するまで永続化コンテキストは はトランザクションが完了するまで管理されます。は
EntityManager.isOpen
メソッドは、エンティティ・マネージャが が開かれているかどうかを示します。このメソッドはisOpen
メソッドは、エンティティ・マネージャが閉じられるまで真を返します。 を返します。 これがどのように動作するかを実際に理解するためには、エンティティ・マネージャとコンテキストの関係を理解することが不可欠です。
エンティティマネージャはエンティティにアクセスするためのパブリックインタフェースですが、エンティティはエンティティマネージャに接続されたコンテキストに存在します。異なるタイプのコンテキストのライフサイクルを理解することで、あなたの質問に答えることができます。
永続化コンテキストには、さまざまなタイプがあります。Java EEアプリケーションでは、1つのコンテクストに対して トランザクション・スコープの永続性コンテキスト または 拡張パーシステンスコンテキスト . JSEアプリケーションでは、コンテキストの性質は 開発元が管理する .
エンティティマネージャにエンティティを要求すると、そのエンティティが添付されているコンテキストでエンティティを探し、そこでエンティティが見つかればそれを返し、そうでなければデータベースからエンティティを取り出します。それ以降、このエンティティをコンテキストで呼び出すと、同じエンティティが返されます。
トランザクションスコープ
トランザクションスコープの永続化コンテキストを使用するJava EEアプリケーションでは、最初にエンティティマネージャにアクセスするとき、現在のJTAトランザクションにコンテキストがあるかどうかをチェックします。コンテキストがまだ存在しない場合、新しいコンテキストが作成され、エンティティマネージャはこのコンテキストにリンクされます。そして、エンティティがデータベースから読み込まれ(キャッシュがあればそこから)、コンテキストに配置されます。トランザクションが終了すると(コミットまたはロールバック)、コンテキストは無効となり、その中のエンティティはすべて切り離される。これはステートレスセッションBeanの古典的なシナリオである。
@PersistenceContext(unitName="EmplService")
EntityManager em;
これはまた、トランザクションをどのように設計するかによって、複数のコンテキストを持つことになる可能性があることを意味します。
拡張パーシステンスコンテキスト
ステートフルセッションBeanを使用するJava EEアプリケーションでは、Beanが削除されるまでコミットしたくないので、コンテキストが複数のBeanの起動に耐えられるようにしたいかもしれませんね?そのような場合、拡張永続化コンテキストを使用する必要があります。この場合、永続化コンテキストは最初に必要になったときに作成されますが、ステートフルBeanを削除するためにマークするまで無効にはなりません。
@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)
これは、ステートフルセッションビーンズのメソッドのその後の呼び出しで、このビーンに注入されるエンティティマネージャーのインスタンスに関係なく、常に同じコンテキストにアクセスすることを保証し、したがって、その後の呼び出しでも、同じインスタンスが返されることを意味する。
また、Beanが削除されるようにマークされるか、手動でフラッシュするまで、変更内容はフラッシュされることはありません。
アプリケーション管理型
エンティティマネージャーファクトリーとエンティティマネージャーを常に手動でインスタンス化することができます。これは、JSEアプリケーションで一般的に行うことですが、正しいですか?
この種のアプリケーションでは、通常、JTAトランザクションを処理するコンテナがありませんよね?そのため、リソースローカルなトランザクションを使用し、手動で変更をコミットまたはロールバックする責任を負います。
この種のアプリケーションでは、エンティティ・マネージャーをインスタンス化するときに、コンテキストが自動的にアタッチされます。
アプリケーションによっては、ライフサイクルがアプリケーション自体のライフサイクルに付随するグローバルエンティティマネージャを作成することを決定することができます。これは、アプリケーションの全ライフサイクルに対する単一のエンティティマネージャです。この場合、コンテキストはエンティティマネージャと一緒に作成され、破棄されます。
または、アプリケーションのユーザーとの会話(つまりトランザクション)ごとにエンティティマネージャーを作成することもできます。この場合、スコープはあなたによって決定されますが、それでも、あなたのコンテキストは、あなたのエンティティマネージャで作成され、破棄されるでしょう。
関連
-
スレッド "main "での例外 java.util.NoSuchElementException in Java 問題解決済み
-
[解決済み] Spring Data JPAにおけるCrudRepositoryとJpaRepositoryのインターフェースの違いは何ですか?
-
Javaクラスが "Error occurred during initialization of boot layer "というエラーで実行される。
-
セミコロン期待値エラー解決
-
ApiModel と @ApiModelProperty の使用法
-
CAS 5.1.8でhttpをサポートし、認証されていない認可サービスエラーのプロンプトが表示される問題を解決した。
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] JPA EntityManager。なぜmerge()ではなくpersist()を使うのか?
-
[解決済み] なぜJava 8のOptionalは引数で使ってはいけないのか
-
[解決済み】JPA JoinColumnとmappedByの比較
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
実行中にEclipseがポップアップする A Java Exception has occurred
-
型に解決できない エラー解決
-
Git Pull Failed マージされていないファイルがあるため、Pull できません。
-
java -jarコマンドでパッケージを実行すると、無効または破損したjarfile xxxx.jarが表示される。
-
JDK8 の Optional.of と Optional.ofNullable メソッドの違いと使い方を説明する。
-
Javaがリソースリークに遭遇した:'input'が閉じない 解決方法
-
Server Tomcat v9.0 Server at localhost の起動に失敗しました。
-
eclipse 実行 Java、エラー: 選択を起動できず、レシーバーもありません。
-
1分でわかる!恋人の写真をIDEAの背景画像に設定する方法【おすすめ集
-
linux ant Resolve error: main class not found or couldn't be loaded org.apache.tools.ant.launcher.