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.
你可以想象这样的东西:
我有一个包含 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.
你可以想象这样的东西: