@ Transactional 方法调用另一个没有@Transactional 注释的方法?

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

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

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

100018 次浏览

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

如果从属于同一 Spring Bean@Transactional方法中调用具有 @Transactional注释的方法,则所调用的方法事务行为将不会对事务产生任何影响。但是,如果从另一个具有事务定义的方法调用具有事务定义的方法,并且它们属于不同的 Spring Bean,那么被调用方法中的代码将遵循其自己的事务定义。

您可以在 春季交易文件春季交易文件声明性事务管理部分中找到更多的细节。

Spring 声明性事务模型使用 AOP 代理,因此 AOP 代理负责事务的创建。只有当被调用方法与调用方方法属于不同的 SpringBean时,AOP 代理才会处于活动状态。

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

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

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

这取决于 传播水平。这里是所有可能的级别 价值观

例如,在传播级别为 嵌套的情况下,当前事务将“挂起”,并创建一个新事务(注意: 嵌套事务的实际创建只能在特定的事务管理器上工作)

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

默认的传播级别(您称之为“行为”)是 需要。如果调用的“ inner”方法上有 @Transactional注释(或者通过 XML 以声明方式进行处理) ,那么它将在 同一笔交易中执行,例如,“ nothing new”被创建。

The inner method will affect the outer method if the inner method is not annotated with @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,因此它将其事务设置为回滚,但不会影响外部事务。当内部事务启动时,外部事务为 PAUSED,然后在内部事务结束后为 RESUMES。它们彼此独立运行,因此外部事务可以成功提交。