I’m using TransactionTemplate in a Spring Boot application to process user-specific order logic in a loop. I expect that if one user’s processing fails, their changes are rolled back, but the others are committed individually. However, I’m seeing that even after marking the transaction rollback-only (status.setRollbackOnly()), the OrderEntity status is still being persisted as COMPLETED instead of staying PENDING.
Here’s a simplified version of my setup:
users.forEach(user -> {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.executeWithoutResult(status -> {
try {
new UserOrderExecutor(user, context).execute();
} catch (Exception e) {
status.setRollbackOnly();
}
});
});
All the logic inside execute which saves modified orders and modifies user balance are not rolled back for the user.
I tried the following:
But still no luck. Any ideas what I am doing wrong?
There are at least some problems I see with your code.
TransactionTemplate
and it doesn't really add anything, assuming the method this code is in is transactional itself.TransactionTemplate
You should create the TransactionTemplate
only once and you should specify the correct isolation level.
var tx = new TransactionTemplate(transactionManager);
tx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW)
users.forEach(user -> {
tx.executeWithoutResult(x -> new UserOrderExecutor(user, context).execute());
});
This will execute exit operation for a User
in a dedicated transaction and only rollback that specific user.
NOTE: If your list of users is large I would suggest to use Spring Batch to handle the updated users and error handling.