I have an entity with 3 field (id, name and age). I have created a repository (PersonRepository) in which I want to see how Transaction works. I find strange that if I insert a method call inside a method, this does not work as expected.
public void nestedTransaction() {
personRepository.save(new Person(11L, "A1", 26));
childTransaction();
}
@Transactional(propagation = Propagation.REQUIRED)
public void childTransaction() {
personRepository.save(new Person(10L, "A2", 26));
throw new RuntimeException("ExceptionTest child");
}
After the autowiring of PersonRepository that contain the above methods, I call:
try {
serviceTransaction.nestedTransaction();
} catch (Exception e) {
System.out.println("Exception: "+e.getMessage());
}
Please do not pay attention on the fact that I'm using System.out.println instead of logging, this is just a test for understanding @Transactional. However, I expect that in my DB there is the entity (11L, "A1", 26) but not the entity (10L, "A2", 26)) instead I have both. Why this happen?
I already know that I can use transactionTemplate and it works using it. For example:
public void nestedTransaction() {
transactionTemplate.setTimeout(1000);
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
personRepository.save(new Person(11L, "Ale2", 26));
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
childTransaction();
}
});
}
Can anyone explain this behaviour and how to solve it?
You need to put the @Transactional
annotation above the nestedTransaction()
method as well for the transaction to commit. Also, the propagation = Propagation.REQUIRED
property is default, so you don't need to specify it.