当前位置: 首页 > 知识库问答 >
问题:

Spring bootr2dbc transactional:注释哪种方法

荆弘伟
2023-03-14

我正在使用带有webflux的spring boot 2.4.2连接到postgres数据库。我在使用事务性代码时观察到了一个我不理解的行为。

为了展示这种行为,我创建了一个示例应用程序,试图将行添加到两个表中;表“a”和表“b”。对表“a”的插入预计将失败,并出现重复密钥冲突。考虑到使用了事务性,我希望不会向表“b”中添加任何行。

然而,根据我用哪个方法注释事务,我会得到不同的结果。

如果我对controller方法进行注释,事情会按预期进行,并且表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);
    }

如果我将事务注释从控制器移动到doSomething(),则事务仍按预期工作。但是,如果我将@事务性注释移动到内部()。表“b”中添加了一行。

此示例的完整代码如下:https://github.com/alampada/pg-spring-r2dbc-transactional

我不明白为什么将注释移动到内部()方法会导致事务处理问题。你能解释一下吗?


共有1个答案

秦时铭
2023-03-14

来自Spring参考文档:使用@Transactional

在代理模式(默认)下,只有通过代理传入的外部方法调用被拦截。这意味着自我调用(实际上,目标对象内的一个方法调用目标对象的另一个方法)即使调用的方法标记为@Transactional,也不会在运行时导致实际事务。此外,必须完全初始化代理以提供预期的行为,因此您不应该在初始化代码(即@PostConstruct)中依赖此功能。

这里,从doSomething()到internal()的调用是一个自调用。

请注意,Spring框架的声明性事务支持是通过AOP代理启用的。

Spring参考文档:了解AOP代理将清楚地说明为什么自调用不能在代理上工作。一定要通读这一节,首先要理解的关键是main(..)中的客户机代码

 类似资料:
  • 问题内容: 你应该将放置在类和/或它们的方法中,还是更好地注释使用DAO对象调用的Service类?还是对两个“层”都进行注释是否有意义? 问题答案: 我认为交易属于服务层。这是了解工作单元和用例的人。如果你将多个DAO注入到一个服务中,而这些DAO需要在单个事务中一起工作,那么这是正确的答案。

  • 本文向大家介绍PowerShell单行注释、多行注释、块注释的方法,包括了PowerShell单行注释、多行注释、块注释的方法的使用技巧和注意事项,需要的朋友参考一下 PowerShell的注释符分为行注释符和块注释符。行注释符使用井号(#)引起一行;块注释符使用“<#”和 “#>”来引起一段注释。 行注释符 举例如下: 块注释符、多行注释 举例如下: 这是小编每次写脚本之前,都会定义的一段关于脚

  • 问题内容: hibernate注释应该放在哪里? 它是我的实例变量上方的线吗?还是在吸气剂之前?还是在二传手之前?还是真的不重要吗? 非常感谢 问题答案: 您可以将它们放在 野外 或 吸气剂上 。从《 Hibernate注释参考指南》中: 2.2.1。将POJO标记为持久实体 (…) 根据您是否注释字段或方法,Hibernate使用的访问类型将是字段或属性。EJB3规范要求您在将要访问的元素类型上

  • 问题内容: 你应该将放置在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的类?还是对两个“层”都进行注释是否有意义? 问题答案: 我认为交易属于服务层。这是了解工作单元和用例的人。如果您将多个DAO注入到一个服务中,而这些DAO需要在单个事务中一起工作,那么这是正确的答案。

  • 对于用@X注释的类中的方法或用@X注释的方法,我需要一个切入点。我还需要注释对象。如果类和方法都被注释,我更喜欢将方法注释作为参数。 我尝试了以下操作,这会产生“绑定不一致”的警告。(为什么不直接将其设置为null?) 以下内容创建了“穿过切入点中的“||”的参数x的不明确绑定”警告。(在我看来,这不一定有意义:为什么不绑定第一个短路评估?) 如果存在类和方法注释,则将前面的尝试拆分为两个,自然会

  • 问题内容: 休眠注释应该放在哪里? 它是我的实例变量上方的线吗?还是在吸气剂之前?还是在二传手之前?还是真的不重要吗? 非常感谢 问题答案: 您可以将它们放在 野外 或 吸气剂上 。从《 Hibernate注释参考指南》中: 2.2.1。将POJO标记为持久实体 (…) 根据您是否注释字段或方法,Hibernate使用的访问类型将是字段或属性。EJB3规范要求您在将要访问的元素类型上声明注释,即,