0

ユーザースレッド設計ごとに JPA EntityManager を実装する方法を知りたいです。EM は軽量オブジェクトであるため、ユーザー スレッドごとに作成してもオーバーヘッドは発生しません。私が解決したい問題は、(コントローラーを介して) バックエンド サービスへの複数の (並列) JSON/AJAX 呼び出しを含む単一の JSP ページです。

Open EM In View Filter を使用して、Entity Manager (永続化コンテキストを拡張) を使用しています。それはうまく機能しますが、ページごとに 1 つのユーザー スレッド (たとえば、json 呼び出し) がある場合、つまりシリアル方式で em にアクセスする場合のみです。ただし、emインスタンスが共有されているため、複数のスレッドからサービスを呼び出すと、目的が解決されず、奇妙なエラーが発生します(コレクションへのアクセスが共有されることもあれば、接続が閉じられることもあります)。

Spring 3 で JPA を使用し、3.5 を休止状態にしています。以下のように、サービスにエンティティ マネージャー (拡張) を挿入します。

@PersistenceContext(type = PersistenceContextType.EXTENDED)
protected EntityManager em;

私の読み取り専用サービスメソッドには、次のように注釈が付けられています

<tx:method name="get*" read-only="true" propagation="SUPPORTS"/>

他のすべてのメソッドには、次のように注釈が付けられています

<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>

私はアプリケーション管理を避けたいので、代わりに EntityManagerFactory を注入しませんでした。また、EntityManager をスプリング コントローラーに挿入することを選択した場合、同じコントローラーが 2 つのスレッドから並行して呼び出されると、まだ問題が発生します。

emへのスレッドセーフなアクセスを実現するエレガントな方法はありますか? また、事態をさらに複雑にするエンティティ オブジェクトのロックも避けたいと考えています。

同じページからの複数の ajax 呼び出しは、最新の Web アプリケーションでは非常に一般的な設計であるため、これを実現するためのシンプルで宣言的な方法が必要であると思います (インターセプターなどを使用して休止状態セッションを手動で管理することに戻る必要はありません)。

4

3 に答える 3

2

私はあなたの問題をよく理解していません。

スレッドごとのエンティティ マネージャーはデフォルトの動作ですが、明示的にオーバーライドしましたEXTENDED。として構成する特定の理由はありますEXTENDEDか? そうでない場合は、削除するだけです。

@PersistenceContext
protected EntityManager em; 
于 2012-07-02T11:31:40.167 に答える
0

Spring には Thread スコープがあり、デフォルトでは無効になっています (セクション4.5 Bean スコープを参照してください)。

スレッドスコープの Bean
Spring 3.0 の時点で、スレッドスコープが利用可能ですが、デフォルトでは登録されていません。詳細については、 のドキュメントを参照してくださいSimpleThreadScope。このカスタムスコープまたはその他のカスタムスコープを登録する方法については、セクション4.5.5.2 「カスタムスコープの使用」を参照してください。

スコープを有効にすると、エンティティマネージャーを次のように定義できますscope=thread

于 2012-07-02T11:01:08.873 に答える
0

これは EM/Sessions を操作する最も標準的な方法であり、OpenSessionInViewFilter (または Interceptor) などの標準ツールがあり、HTTP リクエストがサーブレット コンテナーに入ったときにセッションを作成します。または、AOP の助けを借りてセッションを作成する Spring Transactional サポートにすることもできます。ここでの重要なポイントは、既存のメカニズムを使用するか、拡張機能がある場合は少なくともそれらをコピーして貼り付けることです。Spring は、TransactionSynchronizationManager の助けを借りて、リソースをスレッドにバインド/アンバインドすることでこれを行います。Spring ソースを見ることができます。またはリソースをスレッドにバインドするために同じ手段を使用する会話ごとのセッション パターンの例を次に示します。

于 2012-07-02T11:28:49.813 に答える