0

2 つのアプリケーションがあります。1 つはアプリケーション クライアント、もう 1 つは EJB プロジェクトです。私のクライアントはサーバー側への参照を持っています.Container Managed BeanトランザクションはBeanで使用されています.次のステートメントを使用してエンティティマネージャーをBeanに注入できません.

@PersistenceContext(unitName = "DBService")
private EntityManager em;

サーバー側にメッセージ駆動型 Bean、2 つのステートレス Bean、およびシングルトン Beanがあります。メッセージ駆動型 Bean から 2 つのステートレス Bean をローカルに注入しました。JMS メッセージのメッセージ タイプ (サーバーまたはクライアントから送信されたもの) に応じて、メッセージ駆動型 Bean は関連するステートフル Bean のビジネス メソッドを呼び出します。また、ステートレス Bean のそれぞれがシングルトン Bean を注入します。 .

シングルトン Bean のエンティティにいくつかの変更を加え、エンティティのいくつかのフィールドを更新し、jms メッセージをクライアントまたはサーバーに送信しています。メッセージが 2 つのステートレス Bean によって処理される場合、singleton Bean のビジネス メソッドが呼び出されます。たとえば、エンティティのフィールドを変更しました。次に、シングルトン Bean が jms メッセージをクライアントに送信し、クライアントが何らかの作業を行い、メッセージをサーバーに送り返し、サーバーがこのメッセージをメッセージ駆動型 Bean で消費し、関連するステートレス Bean のビジネス メソッドを呼び出します。 、その後、ステートレス平均はシングルトン Bean のビジネス メソッドを呼び出します。次に、データベースからクエリを実行していますが、変更されたエンティティの最新の状態を確認できません。私の変更は上書きされます。Singleton Bean の EntityManager は、複数の Bean から注入されると、エンティティの状態を正しく保持できないと思いました。同じシングルトン Bean インスタンスを接続プールから取得する必要があると考えました。私はこれについて深刻な問題を抱えています。

私の検出は正しいと思いますか? または私は何か間違ったことをしていますか?

問題: ステートレス Bean がシングルトン Bean のメソッドを呼び出すと、新しいトランザクションが開始され、次に 2 番目のステートレス Bean がシングルトン Bean のメソッドを呼び出し、それもトランザクションを開始しますが、前のトランザクションはコミットされず、2 つのトランザクションは変更を認識していないと思いますお互いが作ったもの。しかし、これを解決する方法がわかりません。Bean 管理のトランザクションを使用することは、シングルトン Bean の優れたソリューションですか?

4

1 に答える 1

0

デフォルトでは、 の注釈が付けられた Bean@Singletonは、コンテナーで管理され、ロック モードを使用しLockType.WRITE、明示的に適用できます@ConcurrencyManagement(CONTAINER)

いずれかのメソッドがクライアントによって呼び出されている場合、他のすべてのリクエストは、前の呼び出しが戻るまで待機する必要があります。ここでは、シングルトン Bean のエントリ メソッドにロックを適用し、その中から他のメソッドを呼び出すことができます。

を使用して、メソッド レベルで注釈を付けることもできます@Lock(LockType.WRITE)。したがって、呼び出しの順序は、クライアントによって呼び出される順序に関係します。


編集:シングルトン Bean への同時アクセスはシリアル化され、メソッドにはデフォルトでREQUIREDトランザクション属性があります。

したがって、コンテナーは、クライアントのトランザクション コンテキストで Bean のメソッドを呼び出します。したがって、ステートレス Bean からシングルトン Bean にまたがる個々のトランザクションがあります。

Stateless Bean A ----->                          ---> Read/Write 
Stateless Bean B ----->  |C|B| Singleton --> |A| ---> Read/Write
Stateless Bean C ----->                          ---> Read/Write

上記のように、Bean B & C からのリクエストは、A が終了するまでシリアル化/エンキューされます。したがって、すべてのリクエストは他に影響を与えることなく分離して処理されますが、おそらくパフォーマンスのボトルネックにつながる可能性があります。

@Lock(LockType.WRITE)共有データを変更する@Lock(LockType.READ)メソッドとそれらにアクセスするメソッドに対して、メソッドレベルのロックを適用できます。

于 2012-10-15T08:44:17.990 に答える