Transaction marked as rollback only: How do I find the cause
When you mark your method as @Transactional
, occurrence of any exception inside your method will mark the surrounding TX as roll-back only (even if you catch them). You can use other attributes of @Transactional
annotation to prevent it of rolling back like:
@Transactional(rollbackFor=MyException.class, noRollbackFor=MyException2.class)
I finally understood the problem:
methodA() { methodB()}@Transactional(noRollbackFor = Exception.class)methodB() { ... try { methodC() } catch (...) {...} log("OK");}@TransactionalmethodC() { throw new ...();}
What happens is that even though the methodB
has the right annotation, the methodC
does not. When the exception is thrown, the second @Transactional
marks the first transaction as Rollback only anyway.
To quickly fetch the causing exception without the need to re-code or rebuild, set a breakpoint on
org.hibernate.ejb.TransactionImpl.setRollbackOnly() // Hibernate < 4.3, ororg.hibernate.jpa.internal.TransactionImpl() // as of Hibernate 4.3
and go up in the stack, usually to some Interceptor. There you can read the causing exception from some catch block.