Spring TransactionManager - 提交不起作用

时间:2012-04-10 08:58:04

标签: java jdbc transactions spring-batch transactionmanager

我正在尝试创建基于Spring的解决方案,以便在MySQL 5.5服务器上运行批量SQL查询。 “查询”是指任何编译的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)

我循环遍历一个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语句后提交),应该做些什么。

3 个答案:

答案 0 :(得分:8)

您无法代理私有方法。即你在这里的@Transactional没有效果。将方法拉到您的父接口,它应该工作。除非您启用了proxyTargetClass设置,否则不推荐使用。

答案 1 :(得分:3)

当您从同一个班级内拨打executeSingleQuery()时,您不会通过代理,因此交易注释将无效。

您正在混合声明性和程序化交易,大概您想要REQUIRES_NEW,这样您就可以删除无意义的@Transactional注释,并在设置Propagation.REQUIRES_NEW时使用DefaultTransactionDefinition

此外,您可能希望在transactionManager.commit(status)块中移动try,当前代码回滚,然后在Exception发生时尝试提交。

答案 2 :(得分:0)

我们使用@Rollback(value = false)注释来解决您面临的问题。