88

以下の方法があります。

public Profile readUser(String email){
    EntityManager em = EMF.get().createEntityManager();
    return em.find(Profile.class, email);
}

上記のエンティティマネージャーの使用法は大丈夫ですか?または、emを閉じる必要がありますか?何か提案がありますか?

4

1 に答える 1

141

答えは次のとおりと思います。

エンティティマネージャは、エンティティが存在するコンテキストにアクセスするための鍵です。アプリケーションがJSEアプリケーションの場合、コンテキストの平均余命を考慮する必要があります。

ユーザーの要求ごとにエンティティマネージャーを作成するとします。したがって、特定のリクエストに参加している間は、エンティティマネージャを開いたままにし、それが終了したら閉じます。

JSEアプリケーションでは、エンティティマネージャーをアプリケーションの存続期間中ずっと開いたままにしておき(大量のデータを処理していないと仮定して)、アプリケーションがシャットダウンしたときにアプリケーションを閉じたいと考えているかもしれません。

結論として、それを開くときと閉じるときは、戦略と設計に完全に依存します。コンテキスト内のエンティティが不要になったら閉じます。

あなたの例では、それは明らかではありませんが、メソッドでEMを作成しているので、戻る前にそれを閉じる必要があります。そうしないと、再びアクセスできなくなります(レジストリに保持していない限り、これはコードでは明らかではありません)。

閉じないと、使用を終えた後でも、エンティティはアタッチされたままになります。EMにアクセスできなくなった場合でも、コンテキストは存続します。

JPA仕様には詳細が含まれています。セクション7.7アプリケーション管理の永続コンテキストでは、次のように述べています。

アプリケーション管理のエンティティマネージャーを使用する場合、アプリケーションは永続プロバイダーのエンティティマネージャーファクトリと直接対話して、エンティティマネージャーのライフサイクルを管理し、永続コンテキストを取得して破棄します。

このようなアプリケーション管理の永続コンテキストはすべてスコープが拡張されており、複数のトランザクションにまたがることができます。

EntityManagerFactory.createEntityManagerメソッド EntityManager closeisOpenメソッドは、アプリケーション管理のエンティティマネージャとそれに関連する永続コンテキストのライフサイクルを管理するために使用されます。

拡張永続コンテキストは、を使用してエンティティマネージャが作成された時点から、を使用 EntityManagerFactory.createEntityManagerしてエンティティマネージャが閉じられるまで存在しEntityManager.closeます。

アプリケーション管理のエンティティマネージャから取得された拡張永続コンテキストは、トランザクションとともに伝播されないスタンドアロンの永続コンテキストです。

[...]このEntityManager.closeメソッドは、エンティティマネージャーを閉じて、永続コンテキストとその他のリソースを解放します。closeを呼び出した後、アプリケーションは、 とEntityManagerを除いてインスタンスでそれ以上のメソッドを呼び出さないようにする必要があります。そうしないと、がスローされます。トランザクションがアクティブなときにcloseメソッドが呼び出された場合、永続コンテキストはトランザクションが完了するまで管理されたままになります。getTransactionisOpenIllegalStateException

このEntityManager.isOpenメソッドは、エンティティマネージャが開いているかどうかを示します。このisOpenメソッドは、エンティティマネージャーが閉じられるまでtrueを返します。これがどのように機能するかを実際に理解するには、エンティティマネージャーとコンテキストの関係を理解することが重要です。

したがって、ご覧のとおり、エンティティマネージャーは、エンティティにアクセスするためのパブリックインターフェイスですが、エンティティは、エンティティマネージャーに接続されたコンテキストに存在します。さまざまなタイプのコンテキストのライフサイクルを理解することで、質問に答えることができます。

永続コンテキストにはさまざまなタイプがあります。Java EEアプリケーションでは、トランザクションスコープの永続コンテキストまたは拡張永続コンテキストのいずれかを使用できます。JSEアプリケーションでは、コンテキストの性質は開発者によって制御されます。

エンティティマネージャにエンティティを要求すると、アタッチされたコンテキストでエンティティが検索され、そこでエンティティが見つかった場合はそれが返されます。それ以外の場合は、データベースからエンティティが取得されます。コンテキスト内でのこのエンティティの後続の呼び出しは、同じエンティティを返します。

トランザクションスコープ

トランザクションスコープの永続コンテキストを使用するJavaEEアプリケーションでは、エンティティマネージャに最初にアクセスするときに、コンテキストがまだ存在しない場合、現在のJTAトランザクションにコンテキストがアタッチされているかどうかがチェックされ、新しいコンテキストが作成され、エンティティマネージャがリンクされます。この文脈に。次に、エンティティがデータベースから読み取られ(存在する場合はキャッシュから)、コンテキストに配置されます。トランザクションが終了すると(コミットまたはロールバック)、コンテキストは無効になり、その中のエンティティはすべて切り離されます。これは、ステートレスセッションBeanの古典的なシナリオです。

@PersistenceContext(unitName="EmplService")
EntityManager em;

これは、トランザクションの設計方法によっては、複数のコンテキストになってしまう可能性があることも意味します。

拡張永続コンテキスト

ステートフルセッションBeanを使用するJavaEEアプリケーションでは、Beanが削除のマークを付けられるまでコミットしたくないので、コンテキストが複数のBean呼び出しに耐えられるようにしたい場合があります。そのような場合は、拡張永続コンテキストを使用する必要があります。この場合、永続コンテキストは最初に必要になったときに作成されますが、ステートフルBeanに削除のマークを付けるまで無効になりません。

@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)

つまり、ステートフルセッションBeanメソッドの後続の呼び出しでこのBeanに注入されるエンティティマネージャーのインスタンスに関係なく、常に同じコンテキストにアクセスできるため、後続の呼び出しでも同じものが返されます。インスタンス、同じコンテキストであるため。

また、Beanに削除のマークが付けられるか、手動でフラッシュするまで、変更はフラッシュされません。

アプリケーション管理

エンティティマネージャファクトリとエンティティマネージャはいつでも手動でインスタンス化できます。これは、JSEアプリケーションで通常行うことですが、そうですか?

この種のアプリケーションの場合、通常、JTAトランザクションを処理するためのコンテナーはありません。したがって、リソースローカルトランザクションを使用し、変更を手動でコミットまたはロールバックする責任があります。

この種のアプリケーションでは、エンティティマネージャーをインスタンス化すると、コンテキストが自動的にアタッチされます。

アプリケーションに応じて、ライフサイクルがアプリケーション自体のライフサイクルに関連付けられているグローバルエンティティマネージャーを作成することを決定できます。これは、アプリケーションの存続期間全体にわたって単一のエンティティマネージャーです。この場合、コンテキストはエンティティマネージャで作成および破棄されます。

または、アプリケーションユーザーとの会話(つまりトランザクション)ごとにエンティティマネージャーを作成することもできます。この場合、スコープはユーザーによって決定されますが、それでも、コンテキストはエンティティマネージャーで作成および破棄されます。

于 2012-05-26T01:51:45.717 に答える