Spring事务管理器:回滚不起作用

时间:2013-04-25 13:31:21

标签: spring transactions spring-transactions transactionmanager

我希望在事务块中执行一些插入查询,如果有任何错误,将回滚所有插入。

我正在使用MySQL数据库和 Spring TransactionManager 。 表类型也是InnoDB

我按照here提到的步骤完成了我的配置。

以下是我的代码(目前只有一个查询)

TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = null;

status = transactionManager.getTransaction(def);
jdbcTemplate.execute(sqlInsertQuery);
transactionManager.rollback(status);

Spring config xml:

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

数据源配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="initialSize" value="${jdbc.initialSize}" />
    <property name="maxActive" value="${jdbc.maxActive}" />
    <property name="minIdle" value="${jdbc.minIdle}" />
    <property name="maxIdle" value="${jdbc.maxIdle}" />
    <property name="testOnBorrow" value="${jdbc.testOnBorrow}" />
    <property name="testWhileIdle" value="${jdbc.testWhileIdle}" />
    <property name="testOnReturn" value="${jdbc.testOnReturn}" />
    <property name="validationQuery" value="${jdbc.validationQuery}" />
    <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
    <!--<property name="removeAbandoned" value="true"/> <property name="removeAbandonedTimeout" 
        value="10"/> <property name="logAbandoned" value="false"/> -->
    <property name="numTestsPerEvictionRun" value="${jdbc.numTestsPerEvictionRun}" />
</bean>

此代码完美正常,并且插入了记录。 但回滚不起作用!它执行回滚语句没有任何错误,但没有任何效果。

任何人都可以指导我哪里出错了吗?

2 个答案:

答案 0 :(得分:3)

问题似乎是您的数据源未设置为自动关闭。

<property name="defaultAutoCommit" value="false"/>

试一试。我从来没有在代理之外使用过TransactionManager,所以我不确定是否有任何其他陷阱直接使用它,但是我建议你看一下AOP交易或者便利的AOP代理注释@Transactional只是因为它更常见

答案 1 :(得分:1)

修改

我终于可以通过执行以下操作解决此问题:

dmlDataSource.setDefaultAutoCommit(false); //set autocommit to false explicitly.
Exception ex = (Exception)transactionTemplate.execute(new TransactionCallback() {
                public Object doInTransaction(TransactionStatus ts) {
                    try {
                        dmlJdbcTemplate.execute(sqlInsertQuery);
                        ts.setRollbackOnly();
                        dmlDataSource.setDefaultAutoCommit(true); // set autocommit back to true    
                        return null;
                    } catch (Exception e) {
                        ts.setRollbackOnly();
                        LOGGER.error(e);
                        dmlDataSource.setDefaultAutoCommit(true); // set autocommit back to true    
                        return e;
                    }
                }
            });

我现在没有使用交易管理器。使用trasactionTemplate并执行以下操作:

Exception ex = (Exception)transactionTemplate.execute(new TransactionCallback() {
                public Object doInTransaction(TransactionStatus ts) {
                    try {
                        dmlJdbcTemplate.execute(sqlInsertQuery);
                        ts.setRollbackOnly();                           
                        return null;
                    } catch (Exception e) {
                        ts.setRollbackOnly();
                        LOGGER.error(e);
                        return e;
                    }
                }
            });

使用@ Moles-JWS的答案后,我现在能够成功回滚。但我想仅在此方法中处理此问题,而不是更改数据源的全局配置。

我可以通过编程方式在这里完成吗?