gpt4 book ai didi

spring - 为什么 Spring 不回滚 RuntimeException?

转载 作者:行者123 更新时间:2023-12-04 05:35:53 25 4
gpt4 key购买 nike

我正在尝试编写一段代码,在其中我可以看到 @Transaction 方法在 RuntimeException 上回滚。这应该是预期的默认行为,但这不是我所看到的。有什么想法吗?

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:mrpomario/springcore/jdbc/jdbc-testenv-config.xml")
@Transactional // Will rollback test transactions at the end
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class TransactionalTest
{
@Autowired
FeedManagerOne feedManagerOne;

@Test
public void test_RuntimeExceptions_Rollback_Behaviour(){
Feed bogus = new Feed("B", "B", false);

assertFalse(feedManagerOne.exists(bogus));

try {
feedManagerOne.createFeedAndThrowRuntimeException(bogus);
} catch (RuntimeException e) { }

// WRONG! feedManagerOne.exists(bogus) SHOULD return false, but returns true.
assertFalse(feedManagerOne.exists(bogus));
}

}

我的服务:

@Service
public class FeedManagerOne {
@Autowired
JdbcTemplate jdbcTemplate;

@Transactional(readOnly = true)
public boolean exists(Feed feed) {
String query = "SELECT COUNT(*) FROM feed WHERE name = ? AND url = ? AND is_active = ?";
int total = jdbcTemplate.queryForInt(query, feed.getName(), feed.getUrl(), feed.isActive());
boolean found = (total == 1);

return found;
}

@Transactional
public boolean createFeedAndThrowRuntimeException(Feed feed) {
String query = "INSERT INTO feed (name, url, is_active) values (?, ?, ?)";
int rowsChanged = jdbcTemplate.update(query, feed.getName(), feed.getUrl(), feed.isActive());
boolean created = (rowsChanged == 1);

if (true)
{
throw new RuntimeException();
}

return created;
}
}

这就是我定义 TransactionManager 的方式:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="mrpomario/springcore/jdbc/testdb/schema.sql"/>
<jdbc:script location="classpath:mrpomario/springcore/jdbc/testdb/test-data.sql"/>
</jdbc:embedded-database>

最佳答案

这是预期的行为。

当您从@Transactional抛出异常(应该导致回滚)时方法中,Spring 将事务标记为在结束时回滚。所以,如果你从最顶层 @Transactional 抛出异常调用堆栈中的方法,事务将立即回滚。

但在你的情况下,你的测试方法是 @Transactional同样,因此您有一个跨越整个测试方法的事务。这意味着尽管调用 createFeedAndThrowRuntimeException() 后事务被标记为回滚,直到测试方法结束才回滚,因此第二次调用 exists()可以观察变化。

因此,如果您想看到回滚,您需要使测试方法成为非事务性的。

我也没有看到<tx:annotation-driven/>在您的配置中。

关于spring - 为什么 Spring 不回滚 RuntimeException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12712742/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com