Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transaction marked as rollback only: How do I find the cause

I am having issues with committing a transaction within my @Transactional method:

methodA() {     methodB() }  @Transactional methodB() {     ...     em.persist();     ...     em.flush();     log("OK"); } 

When I call methodB() from methodA(), the method passes successfuly and I can see "OK" in my logs. But then I get

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly     at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)     at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)     at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)     at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)     at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)     at methodA()... 
  1. The context of methodB is completely missing in the exception - which is okay I suppose?
  2. Something within the methodB() marked the transaction as rollback only? How can I find it out? Is there for instance a way to check something like getCurrentTransaction().isRollbackOnly()? - like this I could step through the method and find the cause.
like image 845
Vojtěch Avatar asked Oct 10 '13 17:10

Vojtěch


People also ask

What is a rollback only transaction?

As a result of an error condition or exception, an application can determine that the current transaction should be rolled back. However, the application should not attempt to rollback the transaction directly.

What is transaction rollback exception?

javax.transaction RollbackException exception is thrown when the transaction has been marked for rollback only or the transaction has been rolled back instead of committed. This is a local exception thrown by methods in the UserTransaction , Transaction , and TransactionManager interfaces.

How do you handle rollback in JPA?

To rollback a transaction you can use @Transaction annotation. You can either implement it on method level or class level. Class level @Transactional(rollbackFor = Exception.


2 Answers

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) 
like image 76
Ean V Avatar answered Sep 27 '22 16:09

Ean V


I finally understood the problem:

methodA() {     methodB() }  @Transactional(noRollbackFor = Exception.class) methodB() {     ...     try {         methodC()     } catch (...) {...}     log("OK"); }  @Transactional methodC() {     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.

like image 41
Vojtěch Avatar answered Sep 27 '22 17:09

Vojtěch