我在Service类中看到了一个被标记为的方法@Transactional
,但是它也在同一类中调用了其他没有被标记为的方法@Transactional
。
这是否意味着对单独方法的调用导致应用程序打开与DB的单独连接或暂停父事务等?
没有任何注释的方法的默认行为是什么,而另一个带有@Transactional
注释的方法调用该方法的默认行为是什么?
Answers:
当您调用没有@Transactional
事务块的方法时,父事务将继续使用新方法。它将使用与父方法(with @Transactional
)相同的连接,以及在调用的方法中引起的任何异常(不使用该异常@Transactional
将导致事务按照事务定义中的配置回滚。
如果@Transactional
从具有@Transactional
相同实例的方法中调用带有注释的方法,则被调用方法的事务行为将不会对事务产生任何影响。但是,如果从具有事务定义的另一个方法中调用具有事务定义的方法,并且它们处于不同的实例中,则被调用方法中的代码将遵循被调用方法中给出的事务定义。
你可以发现在部分中详细声明式事务管理的春季交易文件。
Spring声明式事务模型使用AOP代理。因此,AOP代理负责创建交易。仅当从实例外部调用实例中具有方法的AOP代理才有效。
will follow the transaction definitions given in the called method
。但是,如果该调用来自同一对象实例,则该调用将不会通过负责事务维护的aop代理传播,因此不会产生任何效果。
@Transactional
从不同的对象/实例调用具有定义的方法,那么即使调用方法具有不同的@Transactional
属性,被调用的方法也将遵循其自己的事务定义。
@Transactional标记事务边界(开始/结束),但是事务本身绑定到线程。事务一旦启动,它就会在方法调用之间传播,直到原始方法返回并且事务提交/回滚为止。
如果调用了另一个具有@Transactional批注的方法,则传播取决于该批注的传播属性。
如果内部方法未使用@Transactional注释,则内部方法将影响外部方法。
如果内部方法也用@Transactional注释REQUIRES_NEW
,则会发生以下情况。
...
@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,因此它将设置其事务回滚,但不会影响外部事务。当内部事务开始时,外部事务将暂停,然后在内部事务结束后恢复运行。它们彼此独立运行,因此外部事务可以成功提交。