Spring无法回滚声明式事务

时间:2016-10-08 15:39:26

标签: java mysql spring transactions

我在这个问题上花了几个小时,却一无所获。它让我疯了!所以我告诉自己,为全能的堆栈溢出寻求帮助......

好吧,这是我的问题。我自己在spring aop切入点的add方法中抛出一个RuntimeException,我想要的是DB应该回滚(表中没有新记录)。我可以看到spring得到了RuntimeException并在下面的日志中调用了DataSourceTransactionManager.doRollback方法,但没有任何反应,数据仍然被插入到表中,事务没有回滚。

TRACE [main] org.springframework.transaction.interceptor.RuleBasedTransactionAttribute.rollbackOn(131) | Applying rules to determine whether transaction should rollback on java.lang.RuntimeException: error
TRACE [main] org.springframework.transaction.interceptor.RuleBasedTransactionAttribute.rollbackOn(148) | Winning rollback rule is: null
TRACE [main] org.springframework.transaction.interceptor.RuleBasedTransactionAttribute.rollbackOn(153) | No relevant rollback rule found: applying default rules
TRACE [main] org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCompletion(936) | Triggering beforeCompletion synchronization
DEBUG [main] org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(844) | Initiating transaction rollback
DEBUG [main] org.springframework.jdbc.datasource.DataSourceTransactionManager.doRollback(282) | Rolling back JDBC transaction on Connection [jdbc:mysql://localhost:3306/mydb, UserName=root@localhost, MySQL Connector Java]
TRACE [main] org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(965) | Triggering afterCompletion synchronization
TRACE [main] org.springframework.transaction.support.TransactionSynchronizationManager.clearSynchronization(331) | Clearing transaction synchronization
TRACE [main] org.springframework.transaction.support.TransactionSynchronizationManager.doUnbindResource(243) | Removed value [org.springframework.jdbc.datasource.ConnectionHolder@4a2af8f5] for key [org.apache.commons.dbcp.BasicDataSource@43a4181c] from thread [main]
DEBUG [main] org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(325) | Releasing JDBC Connection [jdbc:mysql://localhost:3306, UserName=root@localhost, MySQL Connector Java] after transaction
DEBUG [main] org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(327) | Returning JDBC Connection to DataSource
顺便说一下,我使用的是MySQL DB,default_storage_engine和table-engine值都是InnoDB(支持事务),默认情况下是autocommit = 1,这里是我的spring transaction config:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
</bean> 

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

<tx:advice id="serviceAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
</tx:advice>

<aop:config>
    <aop:advisor advice-ref="serviceAdvice" pointcut="execution(* com.service..*.*(..))"/>
</aop:config>

Java代码:

package com.dao.impl;

public void add(Event event) throws Exception {

    Connection conn = dataSource.getConnection();

    PreparedStatement pstmt1 = conn
            .prepareStatement("insert into event (message) "
                    + "values ('test1')");
    pstmt1.executeUpdate();


    // pstmt2 execute a wrong SQL which will throw a exception 
    PreparedStatement pstmt2 = conn
            .prepareStatement("insert into event (wrong_column_name) "
                    + "values ('test2')");
    pstmt2.executeUpdate();
}

package com.service.impl;

public void add(Event event) {

        try {
            eventDao.add(event);
        } catch (Exception e) {
            e.printStackTrace();
            // using the RuntimeException to trigger a rollback
            throw new RuntimeException("error");    
        }
}   

非常感谢您的帮助!

0 个答案:

没有答案