A resposta do M. Deinum é boa, mas ainda há outra maneira de conseguir isso que pode ser mais simples para o seu caso, dependendo do estado do seu aplicativo atual.
Você pode simplesmente envolver a chamada para o método assíncrono em um evento que será processado após a confirmação da transação atual, para que você leia a entidade atualizada do banco de dados corretamente todas as vezes.
É bem simples fazer isso, deixe-me mostrar:
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Transactional
public void doSomething() {
// application code here
// this code will still execute async - but only after the
// outer transaction that surrounds this lambda is completed.
executeAfterTransactionCommits(() -> theOtherServiceWithAsyncMethod.doIt());
// more business logic here in the same transaction
}
private void executeAfterTransactionCommits(Runnable task) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
public void afterCommit() {
task.run();
}
});
}
Basicamente, o que acontece aqui é que fornecemos uma implementação para o callback da transação atual e apenas sobrescrevemos o método afterCommit - existem outros métodos lá que podem ser úteis, verifique-os. E para evitar digitar o mesmo código clichê se você quiser usar isso em outras partes ou simplesmente tornar o método mais legível eu extraí isso em um método auxiliar.