2

私が取り組んでいるプロジェクトでは、行レベルのセキュリティを備えた Oracle データベースを使用しています。call DBMS_APPLICATION_INFO.SET_CLIENT_INFO('userId');他の SQL ステートメントを実行する前に、呼び出すことができる必要があります。これを MyBatis 内に実装する方法を見つけようとしています。私が持っていたがうまくいかなかったいくつかのアイデアには、次のものがあります。

試行 1

<select id="selectIds" parameterType="string" resultType="Integer">
      call DBMS_APPLICATION_INFO.SET_CLIENT_INFO(#{userId});
    select id from FOO
</select>

ただし、1 回の JDBC 呼び出しで 2 つのステートメントを使用することはできません。また、MyBatis は JDBC バッチ ステートメントをサポートしていないか、少なくとも私が見つけたものはサポートしていません。

試行 2

<select id="selectMessageIds" parameterType="string" resultType="Integer">
    <![CDATA[
        declare
           type ID_TYP is table of AGL_ID.ID_ID%type;
           ALL_IDS ID_TYP;
        begin
           DBMS_APPLICATION_INFO.SET_CLIENT_INFO(#{userId});
           select ID bulk collect
             into ALL_IDS
             from FOO
        end;
    ]]>
</select>

ただし、プロシージャでデータを返すことはできず、関数でのみデータを返すことができないため、データを返す方法がないことを知ったので、それは私が得た限りです。

試行 3

クライアント情報を設定する単純な MyBatis ステートメントを作成することだけを検討しました。これは、ステートメントを実行する前に呼び出す必要があります。これは最も有望に思えますが、Spring とデータベース接続プーリングを使用しているため、競合状態が心配です。接続が閉じられず、再利用されるため、クライアント情報が流出して他のステートメントに影響を与えないようにしたいと考えています。

ソフトウェア/フレームワークのバージョン情報

Oracle 10g
MyBatis 3.0.5
春 3.0.5

更新
MyBatis Spring 1.0.1 も使用していることを忘れていました

4

2 に答える 2

2

これは、トランザクションの完璧な候補のように聞こえます。@TransactionalDBMS_APPLICATION関数を呼び出すサービス(またはDAO)基本クラスを作成できます。他のすべてのサービスクラスは、ベースを拡張して必要なSQLを呼び出すことができます。

基本クラスでは、DBMS_APPLICATION関数を1回だけ呼び出すようにする必要があります。これを行うには、TransactionSynchronizationManager.hasResource()andbindResource()メソッドを使用して、ブール値または同様のマーカー値を現在のTXにバインドします。この値をチェックして、関数呼び出しを行う必要があるかどうかを判断します。

関数呼び出しがDB内の「作業単位」に対してのみ存在する場合、必要なのはこれだけです。接続中に呼び出しが存在する場合、基本クラスは何らかの方法でfinallyブロックでクリーンアップする必要があります。

基本クラスではなく、別の可能性は、AOPを使用して、メソッド呼び出しの前に関数呼び出しを実行し、最終的なアドバイスとしてクリーンアップすることです。ここで重要なのは、SpringのTransactionInterceptorの後で(つまり、txが開始した後に)インターセプターが呼び出されるようにすることです。

于 2011-08-01T15:08:38.123 に答える
0

最も安全な解決策の 1 つは、特殊化された DatSourceUtils を持つことです

1 : http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/DataSourceUtils.htmlおよび接続時に doGetConnection(DataSource dataSource) および setClientInfo をオーバーライドします

SqlMapClientDaoSupportに独自の抽象化を記述して、クライアント情報を渡します。

于 2011-07-29T06:56:41.507 に答える