代码之家  ›  专栏  ›  技术社区  ›  David Parks

理解Spring事务-当事务方法调用另一个事务方法时会发生什么?

  •  27
  • David Parks  · 技术社区  · 14 年前

    为了理解Spring事务的工作原理,我想知道在以下情况下会发生什么,其中一个方法标记为 @Transactional 调用另一个标记为的方法 @事务性 .

    假设配置使用所有默认设置。

    @Service("myService")
    @Transactional
    public MyService{
       public void myServiceMethod(){
          myDAO.getSomeDBObjects();
       }
    }
    
    @Repository("myDAO")
    @Transactional
    public MyDAOWithUsesBeyondMyService{
       public void getSomeDBObjects(){...}
    }
    

    如果我要进去 MyService.myServiceMethod() 它显然会启动一项交易。然后,钻入 myDAO.getSomeDBObjects() 会发生什么?事务是否已经存在,不会导致新的事务发生,或者我在这里创建两个事务吗?

    关于传播的文献(引述如下)似乎涵盖了这一点,但我想验证一下我的理解,这对我的处女大脑来说是有点难以同时理解的。

    传播 :通常,所有代码 在事务范围内执行 将在该事务中运行。然而, 您可以选择指定 发生以下情况时的行为 事务方法在以下情况下执行 事务上下文已经存在。 例如,代码可以继续运行 在现有交易中 常见情况;或现有 事务可以挂起,并且 事务已创建。春天提供一切 事务传播选项的 熟悉EJB CMT。阅读 事务的语义 春季传播,见第节 10.5.7,“事务传播”。

    1 回复  |  直到 14 年前
        1
  •  39
  •   Sean Patrick Floyd    14 年前

    两个答案:

    a) 别这么做。使用 @Transactional 在服务层或dao层中,但不是两者都有(服务层是通常的选择,因为您可能希望每个服务方法有一个事务)

    b) 如果你这样做,会发生什么取决于 propagation 的属性 @事务性 注释和在本节中描述: 10.5.7 Transaction propagation . 基本上: PROPAGATION_REQUIRED 意味着两种方法将使用相同的事务,而 PROPAGATION_REQUIRES_NEW 启动新事务。

    关于您的评论:

    当然,我一直在阅读,并意识到,当我使用代理时,第二种方法不会被事务代理管理,因此它就像任何其他方法调用一样。

    这在您的情况下是不正确的(仅当两个方法都在同一个类中时)。

    如果bean有方法 a b ,和 电话 ,然后 在实际方法中调用,而不是代理,因为它是从代理内部调用的(bean不知道它被代理到外部世界)。

    proxy      bean  
    a() -->    a()
                |
                V  
    b() -->    b()
    

    但是,在您的情况下,一个服务将有一个注入的dao对象,它本身就是一个代理,所以您会遇到这样的情况:

               proxy      bean
    service    a() -->    a()
                           |
                 /---------/
                 |                 
                 V
    dao        b() -->    b()