我想测试当其中一个数据库更新失败时,使用 Spring JDBC 的 Spring 事务管理是否正常工作。以下是我更新两个数据库表的代码:person 和 contact_info
public void createWithContactInfo(String username, String name, Date dob,
String contactName, String contactPhone, String contactEmail) {
try {
String sqlStmt = "INSERT INTO person (username, name, dob) VALUES (?, ?, ?)";
jdbcTemplateObject.update(sqlStmt, "paul", "Paul", dob);
sqlStmt = "INSERT INTO contact_info(username, customer_name, contact_name, contact_phone, contact_email) VALUES (?, ?, ?, ?, ?)";
jdbcTemplateObject.update(sqlStmt, username, name, contactName,
contactPhone, contactEmail);
} catch (DataAccessException e) {
e.printStackTrace();
}
}
我使用 Spring 声明式事务管理来配置 bean:
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="createWithContactInfo"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="createOperation"
expression="execution(* com.example.db.CustomerJDBCTemplate.createWithContactInfo(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation" />
</aop:config>
<!-- Initialization for data source -->
<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/Customer" />
<property name="username" value="myusername"/>
<property name="password" value="12345"/>
<property name="initialSize" value="10"/>
</bean>
<!-- Definition for customerJDBCTemplate bean -->
<bean id="customerJDBCTemplate" class="com.example.db.CustomerJDBCTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
然后在我的测试代码中,我有:
public class JdbcTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
CustomerDAO dao = (CustomerDAO) ctx.getBean("customerJDBCTemplate");
Date dob = new Date(90, 9, 10);
dao.createWithContactInfo("m9087", "Sam", dob, "David", "123456", "a123@example.com");
}
}
运行主程序后,我收到异常,指出键“PRIMARY”的重复条目“m9087”
。这是预期的,因为 m9087
已存在于 contact_info 表中。但是由于第二个数据库插入在事务中失败,我认为第一个 jdbcTemplateObject.update(sqlStmt, "paul", "Paul", dob);
将不会在事务中提交。不过,我检查了 person
表,它返回了 username=paul
的有效条目:
SELECT * FROM person WHERE username='paul';
这意味着第一次数据库插入成功,尽管第二次数据库插入由于重复键异常而失败。
我的理解是,如果任何数据库操作失败,事务应该回滚并且不会进行提交。但在这种情况下,即使第二次数据库更新由于重复键异常而失败,第一次数据库插入仍然成功。这难道不是事务管理的错误行为吗?我的事务管理设置是否正确?
最佳答案
它不会回滚,因为您捕获了异常。当抛出未经检查的异常时,事务将回滚。然后你用你的捕获 block 吞下它:
catch (DataAccessException e) {
e.printStackTrace();
}
关于java - Spring事务管理在出现错误时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20228228/