2012-04-10 57 views
5

MySQL 5.5サーバーでSQLクエリのバッチを実行するためのSpringベースのソリューションを作成しようとしています。 "query"とは、コンパイルするすべてのSQL文を意味します。そのため、SQLバッチジョブには、たとえばいくつかのCREATE TABLE、DELETE、INSERT文が含まれます。Spring TransactionManager - コミットが機能しません

私はこの目的で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クラスは、単一のSQLステートメントを使用してメソッドを呼び出して、SQLステートメントのコレクションを

@Transactional(propagation = Propagation.REQUIRES_NEW) 

とIループで構成されたメソッドを持っています時間。私はDAOメソッドが完了したとき、私はDBに結果を見ることが期待

simpleJdbcTemplate.getJdbcOperations().execute(sql); 

:メソッド内部 処理と同じくらい簡単です。 しかし、Springジョブの実行が完了してその結果がDBで利用可能になったような場合にのみ表示されます。

私はDAOメソッドの内部でコミット実行しようとしました:私は春のコードをデバッグし、私は私のDAOのメソッドから呼び出すコミットは(流れがラインthis.transactionManager.commit(status);に達するTransactionTemplateによって実行されているのを見ました

@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"); 
} 

をし、すべての呼び出し(コミットするたびにコミット)にDAOメソッドをコミットするために何をすべきかアドバイスしていただきたいと思います。

+0

@Transactionalアノテーションがコミットを行います。あなたのコードでは、トランザクションマネージャへの参照は必要なく、明示的に変更をコミットすると思います。 – ch4nd4n

答えて

8

プライベートメソッドをプロキシすることはできません。あなたがここに持っている@トランザクションは効果がありません。メソッドを親インターフェイスに引き出すと、それが機能するはずです。 proxyTargetClass設定が有効になっていない限り、これは推奨されません。

+0

DAOメソッドをpublicに変更しました - 同じ問題 – aviad

+1

を親インターフェイスにプルアップすると状況が改善しました。シュクラン!:) – aviad

3

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

あなたはREQUIRES_NEWので、あなたが無意味@Transactional注釈を削除し、あなたのDefaultTransactionDefinitionを設定するときPropagation.REQUIRES_NEWを使用することができますしたいおそらく、宣言およびプログラム取引を混合しています。

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

+0

ありがとう、私はあなたの答えをアップアップしたので、それは参考になった(その一部)。しかし、私は2つの答えを受け入れることができません - そしてMadheToは答えて1位でした... – aviad

0

私たちは@Rollback(value = false)アノテーションを使用し、直面している問題を修正しました。

関連する問題