Spring boot r2dbc transactional: 注释哪个方法
Spring boot r2dbc transactional: which method to annotate
我正在使用 spring-boot 2.4.2 和 webflux 连接到 postgres 数据库。
我在使用 @Transactional
时观察到一个我不理解的行为。
为了展示该行为,我创建了一个示例应用程序,它尝试向两个 table 中添加行; table“a”和table“b”。插入 table "a" 预计会因重复键违规而失败。鉴于使用了交易,我希望没有行被添加到 table "b".
但是,根据我用 @Transactional
注释的方法,我得到不同的结果。
如果我注释控制器方法,事情会按预期工作,并且没有行添加到 table 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()
,则事务不会按预期工作。 table "b".
添加一行
这个例子的完整代码在这里:https://github.com/alampada/pg-spring-r2dbc-transactional
我不明白为什么将注释移动到 internal()
方法会导致事务处理出现问题。你能解释一下吗?
来自 Spring 参考文档:Using @Transactional
In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation (in effect, a method within the target object calling
another method of the target object) does not lead to an actual
transaction at runtime even if the invoked method is marked with
@Transactional. Also, the proxy must be fully initialized to provide
the expected behavior, so you should not rely on this feature in your
initialization code (that is, @PostConstruct).
这里从 doSomething() 到 internal() 的调用是一个自调用。
请注意 Spring 框架的声明式事务支持是通过 AOP 代理启用的。
Spring 参考文档:Understanding AOP Proxies 将阐明为什么自调用不适用于代理。请通读以以下开头的部分
这里要理解的关键是 main(..)
中的客户端代码
我正在使用 spring-boot 2.4.2 和 webflux 连接到 postgres 数据库。
我在使用 @Transactional
时观察到一个我不理解的行为。
为了展示该行为,我创建了一个示例应用程序,它尝试向两个 table 中添加行; table“a”和table“b”。插入 table "a" 预计会因重复键违规而失败。鉴于使用了交易,我希望没有行被添加到 table "b".
但是,根据我用 @Transactional
注释的方法,我得到不同的结果。
如果我注释控制器方法,事情会按预期工作,并且没有行添加到 table 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()
,则事务不会按预期工作。 table "b".
这个例子的完整代码在这里:https://github.com/alampada/pg-spring-r2dbc-transactional
我不明白为什么将注释移动到 internal()
方法会导致事务处理出现问题。你能解释一下吗?
来自 Spring 参考文档:Using @Transactional
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object calling another method of the target object) does not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, @PostConstruct).
这里从 doSomething() 到 internal() 的调用是一个自调用。
请注意 Spring 框架的声明式事务支持是通过 AOP 代理启用的。
Spring 参考文档:Understanding AOP Proxies 将阐明为什么自调用不适用于代理。请通读以以下开头的部分 这里要理解的关键是 main(..)
中的客户端代码