Spring 当我在其中调用方法时,@Transactional 不起作用。我该如何解决它?

Spring @Transactional does not work when I call a method inside of it. How can I slove it?

我有一个包含 3 个字段(id、姓名和年龄)的实体。我创建了一个存储库 (PersonRepository),我想在其中查看事务的工作原理。 我觉得很奇怪,如果我在一个方法中插入一个方法调用,这不会像预期的那样工作。

public void nestedTransaction() {
        personRepository.save(new Person(11L, "A1", 26));
        childTransaction();
}

@Transactional(propagation = Propagation.REQUIRED)
public void childTransaction() {
    personRepository.save(new Person(10L, "A2", 26));
    throw new RuntimeException("ExceptionTest child");
}

包含上述方法的 PersonRepository 自动装配后,我调用:

try {
    serviceTransaction.nestedTransaction();
} catch (Exception e) {
    System.out.println("Exception: "+e.getMessage());
}

请不要注意我使用的是System.out.println而不是日志记录,这只是一个理解@Transactional 的测试。但是,我希望在我的数据库中有实体 (11L, "A1", 26) 而不是实体 (10L, "A2", 26)) 而我两者都有。为什么会这样?

我已经知道我可以使用 transactionTemplate 并且它可以正常使用。例如:

public void nestedTransaction() {
    transactionTemplate.setTimeout(1000);
    transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
    transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    personRepository.save(new Person(11L, "Ale2", 26));
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            
       @Override
       protected void doInTransactionWithoutResult(TransactionStatus status) {
            childTransaction();
       }
    });
}

任何人都可以解释这种行为以及如何解决它吗?

您还需要将 @Transactional 注释放在 nestedTransaction() 方法之上,以便提交事务。此外,propagation = Propagation.REQUIRED 属性 是默认值,因此您无需指定它。

事务仅在您从 class 外部调用它时才有效。默认 Spring 使用 AOP 来启动和完成事务,这是一个环绕建议。因此,当您在 class 中调用方法时,它无法通过该代理。您必须使用事务性注释从 class 外部调用的方法,从 class 内部的该方法调用的任何方法(并且在 class 外部的调用堆栈中较低,不会创建新事务) 将加入该交易。 您可以使用 nasted 事务,修改隔离级别等,但不能在同一个 class.

你可以想象这样的东西: