【发布时间】:2022-01-18 00:15:21
【问题描述】:
我正在使用 Spring Boot。我可以使用@Transactional 强制对方法进行事务处理。有时我需要某种方法来使用两个或多个事务。
天真的方法行不通:
public void doActions() {
doAction1();
doAction2();
}
@Transactional
void doAction1() { ... }
@Transactional
void doAction2() { ... }
因为 Spring 使用代理来实现事务。
通常我使用以下方法:
@Autowired
private ThisService self;
public void doActions() {
self.doAction1();
self.doAction2();
}
@Transactional
void doAction1() { ... }
@Transactional
void doAction2() { ... }
它起作用了,但是在 Spring 2.6.0 中,这种循环依赖会导致应用程序无法以可怕的错误启动,除非我将 spring.main.allow-circular-references 设置为 true。
我真的不明白循环引用不好的原因。但显然 Spring Boot 开发人员想要阻止这种设计,所以我想,我最好听从他们的建议。
另一种方法是使用事务管理器并以编程方式调用事务api:
@Autowired
private TransactionTemplate transactionTemplate;
public void doActions() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(@NonNull TransactionStatus status) {
doAction1();
}
});
transactionTemplate.execute(status -> {
doAction2();
return null;
});
它有效,但在我看来它有点冗长和丑陋。
还有其他我错过的方法吗?我应该将 spring.main.allow-circular-references 设置为 true 吗?我担心开发人员将来会使这些循环引用不受支持,因此我需要重新设计我的应用程序。
【问题讨论】:
-
在这种情况下,我经常使用一个单独的“执行器”服务,该服务获取一个 lambda 用于执行。调用可能如下所示:
executor.executeInNewTx(() -> doAction1());等。然后执行程序服务将具有@Transactional注释等。-本质上,问题是您需要跨越服务边界以进行自动事务处理(即拦截器)才能启动. 另一种选择可能是将您的服务分成多个部分,但拥有这样的执行器服务会使生活更轻松。 -
您能否详细说明“使用两个或多个事务的某种方法”是什么意思?通常,事务上下文与当前线程相关联,因此每个线程始终只有 一个 活动事务。此外,您的第一种方法的 doActions() 不会创建任何 tx,因为这些是类内调用(参见例如 this question)
标签: java spring spring-boot