2

bitronix トランザクション マネージャーを使用して分散トランザクションを有効にしようとしています。構成の詳細には次のものが含まれます

  1. OCI JDBC ドライバーと oracle.jdbc.xa.client.OracleXADataSource を使用します。このデータソースは、UCP 接続プーリング データソース (oracle.ucp.jdbc.PoolDataSourceImpl) によってラップされます。
  2. spring JdbcTemplate を使用してクエリを実行します。
  3. Bitronix Transaction Manager を使用して分散トランザクションを処理する
  4. アノテーションを使用した Spring 宣言型トランザクション

私が直面している問題は、JDBCTemplate を使用して実行されたクエリがトランザクションで実行されていないことです。私のテスト ケースは、JDBCTemplate を使用して 2 つのクエリを実行し、クエリの実行後にメソッドが実行時例外をスローしてもロールバックしません。また、接続の自動コミット ステータスが true に設定されていることも確認できました。

<tx:annotation-driven transaction-manager="distributedTransactionManager"/>

<bean id="distributedTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="bitronixTransactionManager"/>
    <property name="userTransaction" ref="bitronixTransactionManager"/>
    <property name="allowCustomIsolationLevels" value="true"/>
</bean>

<bean id="bitronixTransactionManager" factory-method="getTransactionManager"
      class="bitronix.tm.TransactionManagerServices" depends-on="bitronixConfiguration"
      destroy-method="shutdown">
</bean>

The data source is created as follows

    PoolDataSourceImpl pds = new PoolDataSourceImpl();
    try {
        pds.setConnectionPoolName(dataSourceName);
        pds.setConnectionFactoryClassName("oracle.jdbc.xa.client.OracleXADataSource");
        pds.setConnectionFactoryProperties(getOracleDataSourceProperties());
        pds.setDataSourceName(dataSourceName);
        pds.setServerName("v-in-sd-tst-12");
        pds.setPortNumber(1521);
        pds.setUser("ForTestCasesAmit");
        pds.setPassword("adept");
        pds.setMinPoolSize(10);
        pds.setMaxPoolSize(100);
        pds.setMaxIdleTime(1800);

        pds.startPool();
    } catch (SQLException e) {
        throw new RuntimeException("Cannot create project datasource " + dataSourceName, e);
    }
    return pds;

クエリがトランザクションで実行されない理由について何か提案はありますか?

更新 1

jdbcTemplate を使用してクエリを実行し、最後に例外をスローするメソッドの追加

@Transactional(propagation = Propagation.REQUIRED)
public void execute() {
    System.out.println("Starting with the service method");
    jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Date1' WHERE COL2 = 1");

    jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Start Date1' WHERE COL2 = 2");

    waitForUserInput();
    throw new RuntimeException("Rollback Now");
}

更新 2

Oracle JDBC 開発者ガイドには、

「XAConnection から取得した接続のデフォルトの自動コミット ステータスは、Oracle Database 10g より前のすべてのリリースで false です。Oracle Database 10g 以降、デフォルト ステータスは true です。」

Oracle 11g r2 を使用しています。自動コミット ステータスを false にするために分散トランザクションを使用しているときに、どのような構成変更を行う必要があるか考えていますか?

アップデート 3

Oracle ucp PoolDataSource の代わりに bitronix プーリング データ ソースを使用すると、トランザクションが機能します。bitronix PoolingDataSource を使用すると、bitronix は自動コミット ステータスを false に設定できました。2つの違いを理解するために、さらに調査します。

4

2 に答える 2

0

私が見る限り、それらはトランザクションで実行されますが、トランザクションはあなたが期待するものではありません。の場合、各クエリautoCommittrueトランザクションになります。これを回避するには、接続を適切に構成する必要があります。

とはいえ、XAに関するコメント:XAは、ネットワークの問題やタイムアウトなどのコーナーケースでは機能しません。つまり、99.9995%の回数で動作しますが、いくつかの重大なケースでは動作せず、それらはあなたが気にかけているケースです。

XAが最終的に失敗したときに、データ構造が破損しないようにしてください。

XAの代わりに、トランザクションの再実行を可能にするメソッドを評価することをお勧めします。例:データベースAからBにいくつかのレコードを転送するとします。したがって、FOR UPDATE送信された行ごとに行を読み取り、processed列をtrueに設定します。

反対側では、まだ存在していない行のみを追加します。

Bのtxがコミットされたら、Aの行を削除するwhere processed = 'true'か、別の方法でマークを付けます。

つまり、これは必要なだけ実行できます。

[編集]

自動コミットを無効にするには、を呼び出す必要がありますcon.setAutoCommit(false);。もちろん、問題はSpringを使用していることです。そのため、どこでも明示的に接続を要求することはありません。

私の提案:さまざまなメソッドを拡張PoolDataSourceImplしてオーバーライドします。get*Connection()それらを返す前に、自動コミットをfalseに設定してください。JDBCドライバーコードを逆コンパイルして、PoolDataSourceImplそのようなものがすでに含まれているかどうかを確認することもできますが、明らかに含まれていません。

于 2011-05-26T09:41:35.503 に答える
0

このコードを含むメソッドに @Transactional アノテーションが付けられていますか、または Spring にトランザクションでこのメソッドを実行するように指示するアスペクトを定義していますか?

于 2011-05-26T08:02:02.430 に答える