Java 发生错误时Spring事务管理不工作
我想测试当一个数据库更新失败时,使用SpringJDBC的Spring事务管理是否正常工作。下面是我更新两个DB表的代码:person和contact_infoJava 发生错误时Spring事务管理不工作,java,spring,transactions,spring-transactions,Java,Spring,Transactions,Spring Transactions,我想测试当一个数据库更新失败时,使用SpringJDBC的Spring事务管理是否正常工作。下面是我更新两个DB表的代码:person和contact_info public void createWithContactInfo(String username, String name, Date dob, String contactName, String contactPhone, String contactEmail) { try {
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>
在运行主程序后,我得到一个异常,即为键“PRIMARY”复制了条目“m9087”
。这是预期的,因为联系人信息表中已存在m9087
。但是由于第二个DB插入在事务中失败,我认为第一个jdbcTemplateObject.update(sqlStmt,“paul”,“paul”,dob)代码>将不会在事务中提交。但是,我检查了person
表,它返回了username=paul
的有效条目:
SELECT * FROM person WHERE username='paul';
这意味着第一次DB插入成功,即使第二次DB插入由于重复密钥异常而失败
我的理解是,事务应该回滚,如果任何DB操作失败,则不会进行提交。但是在这种情况下,即使第二次DB更新由于重复密钥异常而失败,第一次DB插入仍然成功。这不是交易管理的错误行为吗?事务管理中的设置正确吗?JdbcTemplate不会自动创建将两条更新语句封装在一个事务中的事务
@Autowire
PlatformTransactionManager transactionManager;
public void createWithContactInfo(String username, String name, Date dob,
String contactName, String contactPhone, String contactEmail) {
DefaultTransactionDefinition paramTransactionDefinition =
new DefaultTransactionDefinition();
TransactionStatus status =
transactionManager.getTransaction(paramTransactionDefinition);
try{
... your 2 statmenets here ...
platformTransactionManager.commit(status);
}catch (Exception e) {
platformTransactionManager.rollback(status);
}
}
JdbcTemplate不会自动创建将两个update语句封装在一个事务中的事务
@Autowire
PlatformTransactionManager transactionManager;
public void createWithContactInfo(String username, String name, Date dob,
String contactName, String contactPhone, String contactEmail) {
DefaultTransactionDefinition paramTransactionDefinition =
new DefaultTransactionDefinition();
TransactionStatus status =
transactionManager.getTransaction(paramTransactionDefinition);
try{
... your 2 statmenets here ...
platformTransactionManager.commit(status);
}catch (Exception e) {
platformTransactionManager.rollback(status);
}
}
它不会因为捕捉到异常而回滚。当引发未检查的异常时,事务将回滚。你用你的抓块吞下它:
catch (DataAccessException e) {
e.printStackTrace();
}
它不会因为捕捉到异常而回滚。当引发未检查的异常时,事务将回滚。你用你的抓块吞下它:
catch (DataAccessException e) {
e.printStackTrace();
}
谢谢。这解决了问题,现在我看到当第一个DB插入失败时,第一个DB插入也没有提交。实际上,我遵循了Spring事务示例:在该示例中,它使用try catch
捕获异常。但是场景是不同的,因为在那个例子中,它还在try
块中抛出一个异常。非常感谢。这解决了问题,现在我看到当第一个DB插入失败时,第一个DB插入也没有提交。实际上,我遵循了Spring事务示例:在该示例中,它使用try catch
捕获异常。但是场景是不同的,因为在那个例子中,它还在try
块中抛出一个异常。谢谢Ralph。我正在使用Spring声明性事务管理。因此,与事务相关的所有内容都由bean配置XML文件中的AOP处理。但是如果我使用程序化事务管理,您的解决方案也可以工作。谢谢Ralph。我正在使用Spring声明性事务管理。因此,与事务相关的所有内容都由bean配置XML文件中的AOP处理。但是,如果我使用编程事务管理,您的解决方案也可以工作。