gpt4 book ai didi

java - 为什么@Transactional 在另一项提交失败时不回滚一项提交?

转载 作者:行者123 更新时间:2023-11-30 05:27:49 25 4
gpt4 key购买 nike

所以我有一个类:

@Service
public class MyService {

@Autowired
private RepositoryA repoA;

@Autowired
private RepositoryB repoB;

@Transactional
public void storeEntity(SomeEntity e) {
repoA.save(e);

OtherEntity o = doSomethingWithEntity(e);

repoB.save(o);
}
}

我的方法storeEntity对两个不同的数据源进行两次保存。我希望如果保存到 repoB 失败,或者 doSomethingWithEntity 失败,repoA.save(e) 将回滚。

我想编写一个小测试来确保这种行为:

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceForTransactionTest {
@Autowired
private MyService subject;

@Autowired
private RepositoryA repoA;

@MockBean
private RepositoryB repoB;

@Test
public void repoBShouldNotHaveEntries() {
// given
when(repoB.save(any())).thenThrow(new IllegalStateException("Something wrong with db"));
assertThat(repoB.count()).isEqualTo(0);

// when
SomeEntity e = ...
subject.storeEntity(e);

// then
assertThat(repoA.count()).isEqualTo(0);
}
}

这不起作用,因为抛出异常并且测试失败。当我用 try/catch 包围调用时,我的断言失败,并显示一条消息:repoA 有 1 个条目。如何解决这个问题?

我也尝试过这个:

  @Test
public void repoBShouldNotHaveEntries() {
// given
when(repoB.save(any())).thenThrow(new IllegalStateException("Something wrong with db"));
assertThat(repoB.count()).isEqualTo(0);

// when
SomeEntity e = ...
try {
subject.storeEntity(e);
} catch (Exception e) {
// some output here
}
// then
assertThat(repoA.count()).isEqualTo(0);
}

断言失败。我也尝试过这个:

  @Test
public void repoBShouldNotHaveEntries() {
// given
when(repoB.save(any())).thenThrow(new IllegalStateException("Something wrong with db"));
assertThat(repoB.count()).isEqualTo(0);

// when
SomeEntity e = ...
subject.storeEntity(e);
}

@After
public void tearDown() {
// then
assertThat(repoA.count()).isEqualTo(0);
}
}

也失败了。找到 1 条记录,但我希望 @Transactional 应该回滚。

最佳答案

当您通过 Spring 管理事务时,您实际上是在使用抽象。对于单个数据源(通常称为资源本地事务),事务启动/提交/回滚将按预期工作,但如果使用两个不同的数据源,那么您需要一个能够执行分布式事务的事务管理器,如 BitronixAtomikos Essentials (在开源世界中)。在 EE 应用服务器环境中,此功能由服务器本身提供。 Here是一篇非常古老的文章,值得一读(它使用一个数据库和一个消息代理参与分布式事务,但概念是相同的 - 关键是多个资源)。有关 Bitrionix 和 Spring 的示例配置,请查看 this出来。

关于java - 为什么@Transactional 在另一项提交失败时不回滚一项提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58195292/

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