@Transactional方法在没有@Transactional注释的情况下调用另一个方法?

时间:2011-06-03 03:14:08

标签: java spring spring-transactions transactional

我在Service类中看到了一个标记为@Transactional的方法,但它也在同一个类中调用了一些未标记为@Transactional的其他方法。

这是否意味着对单独方法的调用导致应用程序打开与DB的单独连接或挂起父事务等?

没有任何注释的方法的默认行为是什么是由@Transactional注释的另一个方法调用的?

5 个答案:

答案 0 :(得分:87)

当您在事务块中调用没有@Transactional的方法时,父事务将继续使用新方法。它将使用父方法中的相同连接(使用@Transactional),并且在被调用方法中导致的任何异常(没有@Transactional将导致事务按照事务定义中的配置回滚。

如果在同一实例中使用@Transactional的方法调用带有@Transactional注释的方法,则调用的方法事务行为不会对事务产生任何影响。但是如果使用具有事务定义的另一个方法调用具有事务定义的方法,并且它们位于不同的实例中,则被调用方法中的代码将遵循被调用方法中给出的事务定义。

您可以在spring transaction documentation声明式事务管理部分找到更多详细信息。

Spring声明式事务模型使用AOP代理。所以AOP代理负责创建交易。只有当实例中的方法从实例外部调用时,AOP代理才会处于活动状态。

答案 1 :(得分:18)

  • 这是否意味着对单独方法的调用会导致应用程序打开与DB的单独连接或挂起父事务等?

这取决于propagation level。以下是所有可能的级别values

例如,如果传播级别为NESTED,则当前事务将“挂起”并创建新事务(注意:嵌套事务的实际创建仅适用于特定事务管理器< / em>)

  • 没有使用@Transactional注释的另一个方法调用任何注释的方法的默认行为是什么?

默认传播级别(您称之为“行为”)是REQUIRED。如果调用“内部”方法,其上有@Transactional注释(或通过XML以声明方式进行交易),则它将在相同的交易内执行,例如: “没什么新鲜事”被创造出来。

答案 2 :(得分:8)

@Transactional标记事务边界(开始/结束),但事务本身绑定到线程。一旦事务开始,它就会在方法调用之间传播,直到原始方法返回并且事务提交/回滚。

如果调用另一个具有@Transactional注释的方法,则传播取决于该注释的传播属性。

答案 3 :(得分:0)

您可能已经从以上答复中猜出了问题的答案。如果内部方法未使用@Transactional注释,则内部方法将影响外部方法。

如果内部方法也用REQUIRES_NEW用@Transactional注释,则将发生以下情况。

...
@Autowired
private TestDAO testDAO;

@Autowired
private SomeBean someBean;

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
  testDAO.insertUser(user);
  try{
    someBean.innerMethod();
  } catch(RuntimeException e){
    // handle exception
  }
}


@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
  throw new RuntimeException("Rollback this transaction!");
}

内部方法用REQUIRES_NEW注释,并引发RuntimeException,因此它将其事务设置为回滚,但不会影响外部事务。当内部事务开始时,外部事务将暂停,然后在内部事务结束后恢复运行。它们彼此独立运行,因此外部事务可以成功提交。

答案 4 :(得分:0)

这是我运行代码时从SonarQube获得的东西。

  

使用Spring代理时,请在同一类中调用方法(例如   @Transactional要求不兼容的this.aMethod())   导致运行时异常,因为Spring仅“看到”调用者,并且   没有规定正确调用被调用者。

     

因此,某些呼叫绝对不能在同一个班级内进行:请参见下表,从左侧到右侧,我们不应进行呼叫。

||来自||到||

非@Transactional->>强制性,嵌套,必需,必需_新
强制->>嵌套,从不,不_支持,需要_新
嵌套->>嵌套,从不,不_支持,需要_新
从不->>强制性,嵌套,必需,必需_新
NOT_SUPPORTED->>强制性,嵌套,必需,必需_新
必填或@Transactional->>嵌套,从不,不_支持,需_新
REQUIRES_NEW->>嵌套,永不,NOT_SUPPORTED,REQUIRES_NEW
支持->>强制性,嵌套,永不,不支持,必需,需要_NEW