2012-04-10 213 views
5

我想創建基於Spring的解決方案,以在MySQL 5.5服務器上運行一批SQL查詢。 「查詢」是指任何編譯的SQL語句,因此SQL批處理作業可以包含多個CREATE TABLE,DELETE和INSERT語句。我爲此使用Spring Batch。我的transactionManager配置如下。春季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) 

我環路配置在SQL語句調用帶有一個SQL語句的方法的收集方法一次。 方法內部的處理是非常簡單:

simpleJdbcTemplate.getJdbcOperations().execute(sql); 

我預計DAO方法完成時,我會看到在DB的結果。 但是,它似乎只有在Spring作業執行完成後才能在數據庫中使用結果。

我試圖做我的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"); 
} 

我調試的春天代碼,看到提交我從我的DAO方法調用是TransactionTemplate的(流量達到行執行this.transactionManager.commit(status);和通過沒有例外)

我將不勝感激任何建議應該做什麼,以便使DAO方法提交每次調用(每個SQL語句執行後提交)。

+0

@Transactional註釋負責提交。在你的代碼中,你不需要引用事務管理器,並且明確地提交更改,我想。 – ch4nd4n 2012-04-10 09:23:39

回答

8

您不能代理私人方法。即你在這裏的@Transactional沒有效果。將方法拉到你的父接口,它應該工作。除非您已啓用不建議的proxyTargetClass設置。

+0

更改DAO方法爲public - 同樣問題 – aviad 2012-04-10 09:14:52

+1

將方法拉到父接口有助於這種情況。 Shukran!:) – aviad 2012-04-10 10:51:08

3

當您在同一個班級中呼叫executeSingleQuery()時,您不會通過代理,因此事務註釋將不起作用。

你混合聲明性和程序交易,你大概要REQUIRES_NEW所以你可以設置你的DefaultTransactionDefinition時刪除無意義@Transactional註釋和使用Propagation.REQUIRES_NEW

另外,您可能需要在try塊內移動transactionManager.commit(status),當前代碼將回滾,然後在發生Exception時嘗試提交。

+0

謝謝,我upvote你的答案,因爲它是有益的(其中的一部分)。然而,我不能接受2個答案 - 而MadheTo是第一個回答... – aviad 2012-04-10 11:04:57

0

我們使用了@Rollback(value = false)註釋並解決了您所面臨的問題。