我有一个小型 Spring 应用程序,它读取几个数据库,并在一个数据库中写入一个小表。我有一个带有@Transactional 方法的@Service 注释类。该方法调用 DAO 类(不是 @Repository 注释的)中的方法,该方法首先从表中删除一些行,然后将行插入到同一个表中。
这将部署到 WebLogic。在正常操作下,此应用程序运行良好。
我尝试了一个故意为“insert”添加SQL的实验,并将其部署到我的本地盒子,然后执行执行此服务操作的JMX操作。失败后(预期)我检查了数据库,并确认表完好无损,因此当“插入”失败时它正确回滚了“删除”。
我的问题是我试图模拟类似场景的集成测试没有表现出事务性。我模拟了 JdbcTemplate,所以它执行了删除,但强制它在插入时抛出 DataAccessException。之后,我检查了数据库,行都不见了,所以它并没有像我希望的那样回滚删除。
我在 Spring JTA 包中打开了调试,我看到调试消息打印,说它正在回滚事务。
我正在使用 Atomikos 事务管理器进行测试。以下是我在测试中用于定义“catalogTransactionManager”的上下文的摘录,它是在上下文的其余部分中引用的内容。
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<!-- when close is called, should we force transactions to terminate or not? -->
<property name="forceShutdown">
<value>true</value>
</property>
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout">
<value>300</value>
</property>
</bean>
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="catalogTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<ref bean="atomikosTransactionManager" />
</property>
<property name="userTransaction">
<ref bean="atomikosUserTransaction" />
</property>
</bean>
可能没关系,但这是我的测试方法(有些东西被混淆了):
@Test
public void testInsertFailsAfterDelete() {
List<ErrorMessageInfo> commonErrorMessagesBefore =
myService.
getMyDAO().getCommonErrorMessages(MyService.CHANNEL_NAME);
JdbcTemplate template = mock(JdbcTemplate.class);
myService.getMyDAO().setJdbcTemplate(template);
when(template.update(eq(MyDAO.SQL_DELETE_CHANNEL), any())).
thenReturn(getOrigTemplate().update(MyDAO.SQL_DELETE_CHANNEL, MyService.CHANNEL_NAME));
DataAccessException exception = new DataAccessException("insert failed") {};
when(template.update(eq(MyDAO.SQL_INSERT_ERROR_TO_CHANNEL), anyString(), anyString(), anyInt(), any(), anyInt())).
thenThrow(exception);
try {
myService.updateCommonErrorMessages();
fail();
}
catch (Exception ex) {
assertThat(ex).isEqualTo(exception);
}
finally {
restoreTemplate();
}
List<ErrorMessageInfo> commonErrorMessagesAfter =
myService.
getMyDAO().getCommonErrorMessages(MyService.CHANNEL_NAME);
assertThat(commonErrorMessagesBefore).isEqualTo(commonErrorMessagesAfter);
}
请注意,虽然当我部署到 WebLogic 时,我定义了一个普通的连接池事务数据源,但在我的集成测试中,数据源使用了“org.springframework.jdbc.datasource.DriverManager 数据源”。
我可能会错过什么?
仅仅是因为免费的 Atomikos 事务管理器不是真正的事务性的吗?我可能会错过什么?