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

2022-09-01 14:24:32

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

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

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

@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
   public void getSomeDBObjects(){...}
}

现在,如果我输入它,它显然会开始交易。然后,在深入研究会发生什么之后?交易已经存在的事实是否会导致没有新的交易诞生,或者我在这里创建了两个交易?MyService.myServiceMethod()myDAO.getSomeDBObjects()

关于传播的文档(下面引用)似乎涵盖了这一点,但我想验证我的理解,我的处女大脑一次理解所有东西有点多。

传播:通常,在事务范围内执行的所有代码都将在该事务中运行。但是,您可以选择指定在事务上下文已存在时执行事务方法时的行为。例如,代码可以继续在现有事务中运行(常见情况);或者可以暂停现有事务并创建新事务。Spring提供了EJB CMT中熟悉的所有事务传播选项。要了解 Spring 中事务传播的语义,请参见第 10.5.7 节 “事务传播”。


答案 1

两个答案:

a)不要这样做。在服务层或 dao 层中使用,但不能同时使用(服务层是通常的选择,因为您可能希望每个服务方法一个事务)@Transactional

b) 如果这样做,会发生什么取决于注释的属性,本节将对此进行描述:10.5.7 事务传播。基本上:意味着两种方法将使用相同的事务,同时启动新事务。propagation@TransactionalPROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEW

关于您的评论:

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

这在你的情况下是不正确的(只有当两种方法都在同一类中时)。

如果一个 Bean 有方法和 ,并调用 ,那么是在实际方法上调用的,而不是在代理上调用的,因为它是从代理内部调用的(Bean 不知道它被代理到外部世界)。ababb

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

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

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

答案 2

推荐