108

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

这是否意味着对单独方法的调用导致应用程序打开与数据库的单独连接或暂停父事务等?

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

4

4 回答 4

138

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

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

您可以在Spring 事务文档的声明性事务管理部分中找到更多详细信息。

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

于 2011-06-03T03:17:09.757 回答
24
  • 这是否意味着对单独方法的调用导致应用程序打开与数据库的单独连接或暂停父事务等?

这取决于传播水平。以下是所有可能的级别

例如,如果传播级别是NESTED ,则当前事务将“暂停”并创建新事务(注意:嵌套事务的实际创建仅适用于特定事务管理器

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

默认传播级别(您称之为“行为”)是REQUIRED。如果调用了带有@Transactional注释的“内部”方法(或通过 XML 以声明方式进行事务处理),它将在同一个事务中执行,例如“没有新内容”被创建。

于 2012-01-17T22:38:49.503 回答
9

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

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

于 2011-06-03T12:17:33.397 回答
3

如果内部方法没有使用@Transactional 注解,内部方法将影响外部方法。

如果内部方法也用 @Transactional with 注释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,因此它将其事务设置为回滚,但不会影响外部事务。外部事务在内部事务开始时暂停,然后在内部事务结束后恢复。它们彼此独立运行,因此外部事务可以成功提交。

于 2019-04-05T16:55:20.700 回答