I'm using Spring Boot. I can use @Transactional
to force transaction on a method. Sometimes I need for some method to use two or more transactions.
Naive approach wouldn't work:
public void doActions() {
doAction1();
doAction2();
}
@Transactional
void doAction1() { ... }
@Transactional
void doAction2() { ... }
because Spring uses proxies to implement transactions.
Usually I've used the following approach:
@Autowired
private ThisService self;
public void doActions() {
self.doAction1();
self.doAction2();
}
@Transactional
void doAction1() { ... }
@Transactional
void doAction2() { ... }
It worked, but in Spring 2.6.0 this circular dependency causes application to fail to start with scary error unless I set spring.main.allow-circular-references to true.
I don't really understand the reason why circular references are bad. But apparently Spring Boot developers want to discourage this kind of design, so, I guess, I better follow their advice.
Another approach is to use transaction manager and programmatically call transaction 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;
});
It works but it's a little bit verbose and ugly in my opinion.
Is there any other approaches I missed? Should I just set spring.main.allow-circular-references to true? I'm afraid that developers will make those circular references thing unsupported in the future and I'd need to rework my application because of that.