一尘不染

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

spring

为了了解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()会发生什么?交易已经存在的事实会导致没有新的交易诞生,还是我在这里创建两个交易?

关于Propagation的文档(在下面引用)似乎涵盖了这一点,但是我想验证一下我的理解

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


阅读 1874

收藏
2020-04-16

共1个答案

一尘不染

两个答案:

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

b)如果这样做,会发生什么情况取决于注释的propagation属性,@Transactional并在本节中进行描述:10.5.7事务传播。基本上:PROPAGATION_REQUIRED意味着同一事务将用于两种方法,同时PROPAGATION_REQUIRES_NEW开始新事务。

关于你的评论:

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

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

如果一个bean有方法ab,和a电话b,然后b叫上实际的方法,而不是代理,因为它是从代理中调用(豆不知道它是代理到外面的世界)。

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

但是,在你的情况下,服务将具有注入的dao对象,该对象本身就是代理,因此你将遇到以下情况:

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