An order and its audit log must be saved in
the same transaction.
process() is called from another Spring bean.
@Service
public class OrderService {
public void process(Order order) {
saveOrder(order); // appel interne
}
@Transactional
public void saveOrder(Order order) {
orderRepository.save(order);
auditRepository.save(
new Audit(order.getId())
);
}
}
?
What happens with the @Transactional of saveOrder() ?
In standard Spring proxy mode,
@Transactional is applied when a call
goes through the Spring proxy.
Here, process() directly calls
saveOrder() on the same instance.
Therefore, the call does not go through the proxy, and the transaction
declared on saveOrder() is not created.
Developers might assume that saving the order and the audit log forms a single atomic operation. In reality, this wrapping transaction does not exist in this call path. Spring Data repositories can run their own transactions: a first save might succeed even if a subsequent operation fails.
A @Transactional placed on a method is not
enough: the call must go through the Spring proxy.
A common solution is to move the transactional
method to another Spring bean so the call
can be intercepted.