我在Service类中看到了一个标记为@Transactional
的方法,但它也在同一个类中调用了一些未标记为@Transactional
的其他方法。
这是否意味着对单独方法的调用导致应用程序打开与DB的单独连接或挂起父事务等?
没有任何注释的方法的默认行为是什么是由@Transactional
注释的另一个方法调用的?
答案 0 :(得分:87)
当您在事务块中调用没有@Transactional
的方法时,父事务将继续使用新方法。它将使用父方法中的相同连接(使用@Transactional
),并且在被调用方法中导致的任何异常(没有@Transactional
将导致事务按照事务定义中的配置回滚。
如果在同一实例中使用@Transactional
的方法调用带有@Transactional
注释的方法,则调用的方法事务行为不会对事务产生任何影响。但是如果使用具有事务定义的另一个方法调用具有事务定义的方法,并且它们位于不同的实例中,则被调用方法中的代码将遵循被调用方法中给出的事务定义。
您可以在spring transaction documentation的声明式事务管理部分找到更多详细信息。
Spring声明式事务模型使用AOP代理。所以AOP代理负责创建交易。只有当实例中的方法从实例外部调用时,AOP代理才会处于活动状态。
答案 1 :(得分:18)
这取决于propagation level。以下是所有可能的级别values。
例如,如果传播级别为NESTED,则当前事务将“挂起”并创建新事务(注意:嵌套事务的实际创建仅适用于特定事务管理器< / em>)
默认传播级别(您称之为“行为”)是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