vbe*_*nar 4 java spring spring-boot
我正在使用 Spring Boot。我可以使用@Transactional强制方法进行事务处理。有时我需要某种方法来使用两个或多个事务。
天真的方法是行不通的:
public void doActions() {
doAction1();
doAction2();
}
@Transactional
void doAction1() { ... }
@Transactional
void doAction2() { ... }
Run Code Online (Sandbox Code Playgroud)
因为Spring使用代理来实现事务。
通常我使用以下方法:
@Autowired
private ThisService self;
public void doActions() {
self.doAction1();
self.doAction2();
}
@Transactional
void doAction1() { ... }
@Transactional
void doAction2() { ... }
Run Code Online (Sandbox Code Playgroud)
它有效,但在 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;
});
Run Code Online (Sandbox Code Playgroud)
它有效,但在我看来有点冗长和丑陋。
我还错过了其他方法吗?我应该将 spring.main.allow-circular-references 设置为 true 吗?我担心开发人员将来会使这些循环引用变得不受支持,因此我需要重新设计我的应用程序。
是的。我同意这很丑。您可以创建一个只负责执行事务中的某些代码的服务。与此相同的想法,TransactionTemplate但它用于@Transational管理事务。
@Service
public class TransactionExecutor {
@Transactional(propagation = Propagation.REQUIRED)
public <T> T execute(Supplier<T> action) {
return action.get();
}
@Transactional(propagation = Propagation.REQUIRED)
public void execute(Runnable action) {
action.run();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public <T> T executeInNewTx(Supplier<T> action) {
return action.get();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void executeInNewTx(Runnable action) {
action.run();
}
}
Run Code Online (Sandbox Code Playgroud)
然后注入它来使用它:
@Service
public class FooService {
@Autowired
private TransactionExecutor txExecutor;
public void doActions() {
txExecutor.execute(()->doAction1());
txExecutor.execute(()->doAction2());
}
void doAction1() { ... }
void doAction2() { ... }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4611 次 |
| 最近记录: |