4

すべてのデータベース操作の前にコンテキストを設定する必要があります(Oracleのパッケージレベルの変数を使用してみましたが、パッケージの再コンパイルに問題があるため、DBMS_SESSIONDBMS_APPLICATION_INFOを試してみます)。これにより、特定のユーザー情報をどこでも取得できます。 「JBoss」として識別される数十のデータベース接続ではなく、それ(手順、トリガーなど)が必要です。

@StatelessBeanへの呼び出しをインターセプトするJavaEEインターセプターを作成しました。Oracle関数を呼び出して、セッションコンテキストを設定します(Java EE 6インターセプターでトランザクションがアクティブかどうかを確認する方法のサンプルコードについては、この質問を参照してください)。

私の最初の心配は接続プールでした。最初は、Java EEによって提供されるデフォルトの@PersistenceContext伝播で、すべてが同じ接続/トランザクション/ EntityManagerで実行されることを保証するのに十分だと思いました。finally以前は、インターセプターの最後(ブロック内)ですべての設定を解除するだけで済みました。接続はプールに戻されます。少し壊れやすいように見えましたが、うまくいくと思いました。

次に、Hibernateにはhibernate.connection.release_mode ( hibernate.connection.release_modeに関するHibernateドキュメントorg.hibernate.ConnectionReleaseModeに関するRed Hatドキュメント)というプロパティがあり、 JTAトランザクションを使用する場合のデフォルトの推奨動作はリリースすることであることがわかりました。すべてのステートメントの後の接続(ドキュメントには、同じ基本接続の再取得について何かが書かれていますが、これは私を混乱させました)。

今では、ビジネスメソッドの途中で他の誰かが同じ接続を取得してユーザーコンテキストを混乱させるリスクなしに、このユーザー/操作にのみ表示されるインターセプターに何かを確実に設定できるかどうかさえわかりません。 。私が理解しているように、Oracleデータベースのセッション変数は、トランザクションや@PersistenceContextではなく、接続用に保持されます(データベースは永続コンテキストについて何も知らないため、接続は複数のトランザクションに使用できます)。

関係するすべてのテクノロジーの実装の詳細について学ぶにつれて、これはますます脆弱に見えるので、私はあきらめようとしています。このユーザーコンテキストのアイデアを機能させることはできますか、それともまったく異なるアプローチを試す必要がありますか?また、実装をテスト/デバッグして、並行性の問題が潜んでいないことを確認するにはどうすればよいですか?フレームワークの動作を監視するのに役立つイベントリスナーは見つかりませんでした。サーバーのストレステストを行うプログラムを作成するのは大変な作業であり、とにかく機能するかどうかわからないことに投資することはできません。

私はJBossAS7.1、EJB 3.1、Oracle 10gデータベース、およびJPA 2.0を使用しています(Hibernate固有のAPIは使用していませんが、Hibernateに支えられています)。

4

2 に答える 2

2

個人的には、プールからのJDBC接続に個々のパラメーターを設定しようとはしません。結局のところ、プールの考え方は、すべての接続が同一であるということです。ですから、あなたのインターセプターのアイデアはうまくいくでしょうが、私はそれがどれほど壊れやすいかについても心配しています。その実装のバグは、最も厄介な競合状態になります。

一方、Oracleを使用しているため、EclipseLinkを確認することをお勧めします。これはJPA2を実装し、Oracleから多額の資金提供を受けているため、すべての奇妙な機能をサポートしています。'IsolatedClientSessions'の使用を検討することをお勧めします。個別のセッション設定が必要な仮想プライベートデータベースをサポートしているようです。したがって、セッションコンテキストを変更する必要がある場合は、これが解決策になります。

于 2013-01-05T05:53:28.337 に答える
2

それで、私は最近私が見つけたすべてのことで私自身の質問に答えます。

サーバーの動作を理解するために、JBossの設定を変更して、1つの接続のみのプールを使用するようにしました。これにより、他の誰かが待機をブロックされていることを検出できました。

現在の操作がトランザクション内にある場合(@TransactionAttribute(REQUIRED)など)、トランザクションが終了するまで接続は他の目的には使用されません(他のクライアントは待機する必要があります)。ただし、トランザクションなしでデータベースを読み取ると、ビジネスメソッドが終了する前であっても、データベースを使用していないときに他のクライアントが同じ接続を取得する可能性があります(この動作の標準と実装の量はわかりません)詳細)。

Hibernateはデフォルトですべてのステートメントの後に接続を解放します。そのため、接続は非トランザクション方式で再利用できます。一方、JDBCとJEEには、同じトランザクションを実行している場合に同じ接続を再取得するために必要な機能があります。

しかし、Hibernateが後で再取得する接続を解放するのはなぜですか?Hibernateがそれを解放しなかった場合、一部のJEEサーバーは、ネストされたEJB呼び出しで接続を開き、呼び出し元が再利用できるように開いたままにしておくと、Hibernateが接続をリークしていると考える可能性があります。それはこの投稿で説明されています:

http://www.mail-archive.com/hibernate-dev@lists.jboss.org/msg00612.html

安全のために、保存する必要のある(後でユーザーに提示する)すべてのデータはパラメーターとして明示的に渡されますが、ロギングの目的で、接続を他のクライアントが再利用できないことを認識して、Oracleセッションに保存されているデータを使用しました。トランザクションビジネスメソッドを使用する限り。

更新:コネクタやカスタムデータソースに関連するアプリサーバー固有の設定を使用して、やりたいことができるようです(ここで最良の答えがわからない:https ://developer.jboss.org/thread/250132 )。

于 2013-12-06T13:00:54.967 に答える