我在这个问题上花了几个小时,却一无所获。它让我疯了!所以我告诉自己,为全能的堆栈溢出寻求帮助......
好吧,这是我的问题。我自己在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");
}
}
非常感谢您的帮助!