7

MySQL 5.5 サーバーで SQL クエリのバッチを実行するための Spring ベースのソリューションを作成しようとしています。「クエリ」とは、コンパイルする任意の SQL ステートメントを意味するため、SQL バッチ ジョブには、たとえば、複数の CREATE TABLE、DELETE、および INSERT ステートメントを含めることができます。

この目的のためにSpring Batchを使用しています。

以下のようにtransactionManager構成しました。

    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" />

そしてdataSource

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${batch.jdbc.driver}" />
    <property name="url" value="${batch.jdbc.url}" />
    <property name="username" value="${batch.jdbc.user}" />  
    <property name="password" value="${batch.jdbc.password}" /> 
    <property name="maxIdle" value="10" />
    <property name="maxActive" value="100" />
    <property name="maxWait" value="10000" />
    <property name="validationQuery" value="select 1" />
    <property name="testOnBorrow" value="false" />
    <property name="testWhileIdle" value="true" />
    <property name="timeBetweenEvictionRunsMillis" value="1200000" />
    <property name="minEvictableIdleTimeMillis" value="1800000" />
    <property name="numTestsPerEvictionRun" value="5" />
    <property name="defaultAutoCommit" value="true" />
</bean>

私のDAOクラスには、で構成されたメソッドがあります

@Transactional(propagation = Propagation.REQUIRES_NEW)

そして、一度に 1 つの SQL ステートメントでメソッドを呼び出す SQL ステートメントのコレクションをループします。メソッド内の処理は次のように単純です。

simpleJdbcTemplate.getJdbcOperations().execute(sql);

DAO メソッドが完了すると、結果が DB に表示されることを期待していました。ただし、Spring ジョブの実行が完了したときにのみ、結果が DB で利用可能になるようです。

DAOメソッド内でコミットを試みました:

@Transactional(propagation = Propagation.REQUIRES_NEW)
private void executeSingleQuery(String sql) {
    PlatformTransactionManager transactionManager = (PlatformTransactionManager)context.getBean("transactionManager");


    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setPropagationBehavior(Propagation.REQUIRED.ordinal());

    TransactionStatus status = transactionManager.getTransaction(def);

    try {
        // execute your business logic here
        log.info("about to execute SQL query[" + sql + "]");
        simpleJdbcTemplate.getJdbcOperations().execute(sql);

    } catch (Exception e) {
        log.info("SQL query  was not committed due to exception and was marked for rollback");
        transactionManager.rollback(status);
    }

    transactionManager.commit(status);

    if (transactionManager.getTransaction(null).isRollbackOnly() 
            && transactionManager.getTransaction(null).isCompleted()) {
        log.info("SQL query commited!");
    } else {
        log.info("SQL query  was not committed due to: 1) the transaction has been marked for rollback " +
                "2) the transaction has not completed for some reason");
    }

    log.info("the query has completed");
}

Spring コードをデバッグしたところ、DAO メソッドから呼び出したコミットが TransactionTemplate によって実行されることがわかりました (フローは行に到達し、this.transactionManager.commit(status);例外なく通過します) 。

DAOメソッドをすべての呼び出しでコミットするために何をすべきかアドバイスをいただければ幸いです(実行するすべてのSQLステートメントの後にコミットします)。

4

3 に答える 3

8

プライベート メソッドをプロキシすることはできません。つまり、ここにある @Transactional は効果がありません。メソッドを親インターフェイスにプルすると、機能するはずです。推奨されないproxyTargetClass設定を有効にしている場合を除きます。

于 2012-04-10T09:07:59.033 に答える
3

同じクラス内で fromを呼び出す場合executeSingleQuery()、プロキシを経由しないため、トランザクション アノテーションは効果がありません。

宣言型トランザクションとプログラム型トランザクションを混在させてREQUIRES_NEWいます。おそらく、無意味な@Transactional注釈を削除Propagation.REQUIRES_NEWして、DefaultTransactionDefinition.

また、ブロックtransactionManager.commit(status)内に移動するtryと、現在のコードがロールバックされ、Exceptionエラーが発生したときにコミットが試行されます。

于 2012-04-10T09:45:21.403 に答える
0

注釈を使用して、@Rollback(value = false)直面している問題を修正しました。

于 2015-11-20T22:11:07.113 に答える