I am using Spring 4
, JPA
and Hibernate 5
. I have a service as follows:
@Transactional(rollbackFor = Exception.class)
public methodA() {
// do some stuff
methodB();
}
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public methodB() {
try {
methodC();
} catch (Exception e) {
// only log
}
}
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public methodC() {
// do some stuff
}
What I want to achieve is this: when methodA
is called, everything executed before calling methodB
should be persisted, independently to what happens afterwards. For this reason I added methodB
, the only purpose of which is to create a new transaction, so if the transaction of methodC
rollbacks, the original transaction of methodA
does not rollback as well. So to sum this up, I want the first transaction to commit and the second to rollback in case of failure. Note that methodC
cannot be changed in any way.
This code however does not work and I still get the exception: "TransactionException: Transaction was marked for rollback only; cannot commit"
Any ideas on what I'm doing wrong?
I am using Spring 4, JPA and Hibernate 5. I have a service as follows:
So you're using three methods inside same service
This highlight is important because of how spring AOP works.
If you call method within the same class, then the other methods do not get proxied by @Transaction
so they're still using the same transaction of methodA
.
Therefore you will see exception when the transaction is marked as rollbackOnly
by methodB
So to solve this: You have to move the method methodB
to another service so it will proxy-able by Spring.