我看到一个Service类中有一个被标记为@Transactional
的方法,但是它也调用了同一类中未标记@Transactional
的其他方法。
这是否意味着对不同方法的调用会导致应用程序打开与数据库的单独连接或挂起父事务等操作?
没有任何注释的方法被另一个带有@Transactional
注释的方法调用时,默认行为是什么?
我看到一个Service类中有一个被标记为@Transactional
的方法,但是它也调用了同一类中未标记@Transactional
的其他方法。
这是否意味着对不同方法的调用会导致应用程序打开与数据库的单独连接或挂起父事务等操作?
没有任何注释的方法被另一个带有@Transactional
注释的方法调用时,默认行为是什么?
当您在事务块中调用没有@Transactional
的方法时,父事务将传播到新方法。它将使用来自父方法(带有@Transactional
)的相同连接,并且在被调用的方法(没有@Transactional
)中引起的任何异常都会导致事务根据事务定义进行回滚。
如果您从具有@Transactional
的方法调用具有@Transactional
注释的方法,这两个方法属于同一个Spring Bean,则被调用方法的事务行为不会对事务产生影响。但是,如果您从具有事务定义的另一个方法调用具有事务定义的方法,并且它们属于不同的Spring Bean,则被调用方法中的代码将遵循其自己的事务定义。
您可以在Spring Transaction Management documentation的声明式事务管理部分中找到更多详细信息。
Spring声明式事务模型使用AOP代理,因此AOP代理负责创建事务。仅当被调用方法属于与调用方不同的Spring Bean
时,AOP代理才会处于活动状态。
@Transactional
标记事务的边界(开始/结束),但事务本身绑定到线程。一旦事务启动,它会在方法调用中传播,直到原始方法返回并提交/回滚事务。
如果调用了另一个带有 @Transactional
注解的方法,则传播取决于该注解的传播属性。
如果内部方法没有使用@Transactional
进行注释,则会影响外部方法。
如果内部方法还使用@Transactional
进行注释,并且使用了Propagation.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
,因此它将将其事务设置为回滚但不会影响外部事务。当内部事务开始时,外部事务被暂停,然后在内部事务结束后恢复。它们彼此独立运行,因此外部事务可能会成功提交。
@Transactional
中,您可以指定传播属性,这是类型为@Propagation
的枚举值。 - Tomasz Błachowicz@Transactional
定义的方法,即使调用方法具有不同的@Transactional
属性,被调用方法也将遵循自己的事务定义。 - Arun P Johny