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

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

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

两个答案:

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

b)如果你这样做,会发生什么取决于@Transactional注释的propagation属性,并在本节中描述: 10.5.7事务传播 。 基本上: PROPAGATION_REQUIRED表示两种方法都使用相同的事务,而PROPAGATION_REQUIRES_NEW启动新事务。

关于你的意见:

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

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

如果bean有方法ab ,并且调用b ,则在实际方法而不是代理上调用b ,因为它是从代理中调用的(bean不知道它是代理到外部世界的) )。

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

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

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