如何解决Spring Boot r2dbc 事务性:注释哪个方法
我使用带有 webflux 的 spring-boot 2.4.2 连接到 postgres 数据库。
我在使用 @Transactional
时发现了一个我不明白的行为。
为了展示这种行为,我创建了一个示例应用程序,尝试将行添加到两个表中;表“a”和表“b”。插入表“a”预计会因重复键违规而失败。鉴于使用了事务性,我希望不会将任何行添加到表“b”中。
但是,根据我使用 @Transactional
注释的方法,我会得到不同的结果。
如果我注释控制器方法,事情会按预期工作,并且不会向表 B 添加任何行。
@PostMapping("/")
@Transactional
public Mono<Void> postEntities() {
return demoService.doSomething();
}
DemoService 看起来像这样:
public Mono<Void> doSomething() {
return internal();
}
public Mono<Void> internal() {
Mono<EntityA> clash = Mono.just(EntityA.builder().name("clash").build()).flatMap(repositoryA::save);
Mono<EntityB> ok = Mono.just(EntityB.builder().name("ok").build()).flatMap(repositoryB::save);
return ok.and(clash);
}
如果我将 @Transactional
注释从控制器移动到 doSomething()
,那么事务仍然按预期工作。
但是,如果我将 @Transactional
注释移动到 internal()
,则事务不会按预期工作。一行被添加到表“b”中。
这个例子的完整代码在这里:https://github.com/alampada/pg-spring-r2dbc-transactional
我不明白为什么将注释移到 internal()
方法会导致事务处理出现问题。你能解释一下吗?
解决方法
来自 Spring 参考文档:Using @Transactional
代理模式下(默认),只有外部方法调用 通过代理进入被拦截。这意味着 自调用(实际上,目标对象中的一个方法调用 目标对象的另一种方法)不会导致实际 即使调用的方法被标记为 @交易。此外,代理必须完全初始化以提供 预期的行为,所以你不应该在你的 初始化代码(即@PostConstruct)。
这里从 doSomething() 到 internal() 的调用是一个自调用。
请注意 Spring Framework 的声明式事务支持是通过 AOP 代理启用的。
Spring 参考文档:Understanding AOP Proxies 将阐明为什么自调用不适用于代理。请通读以开头的部分 这里要理解的关键是 main(..) 中的客户端代码
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。