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

Dav*_*rks 27 java spring transactions

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

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

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

@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
   public void getSomeDBObjects(){...}
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我要输入MyService.myServiceMethod()它,显然会启动一个交易.然后,钻进myDAO.getSomeDBObjects()会发生什么?交易已经存在的事实会导致没有新的交易产生,或者我在这里创建两个交易?

关于传播的文档(引用如下)似乎涵盖了这一点,但我想验证我的理解,这对于我的处女大脑来说有点多了解一下.

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

Sea*_*oyd 39

两个答案:

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()
Run Code Online (Sandbox Code Playgroud)

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

           proxy      bean
service    a() -->    a()
                       |
             /---------/
             |                 
             V
dao        b() -->    b()
Run Code Online (Sandbox Code Playgroud)