How to deal the problem "Transaction was marked for rollback only; cannot commit; "?
I'm guessing your service calls some other component that is annotated with @Transactional
, correct? If an exception occurs when calling this other component and is caught in SomeServiceImpl
you will be faced with the exception you describe when the transaction system attempts to commit the transaction in methodB
. Any exception passing an @Transactional
boundary will mark the surrounding transaction as rollback-only, unless you have explicitly told the system otherwise.
If you want the surrounding transaction (i.e. the transaction created for methodB
) to "survive" this exception, you'll need to alter the @Transactional
annotation on the target component (i.e. the component where the Exception is thrown) with noRollbackFor
.
liu246437
Updated on June 05, 2022Comments
-
liu246437 almost 2 years
public class A{ @Async public void methodA(){ someService.methodB(); } } public class someServiceImpl implements someService{ @Transactional(noRollbackFor = Exception.class) public void methodB(){ try{ //to do }catch(Exception e){ log.error(e.getMessage()); } } }
For example, I used the '@ Transactional' to mark my method hope to commit the transaction when error happened.But the problem still happened like this:
org.springframework.orm.jpa.JpaSystemException: Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:314) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:540) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) at com.linkyoyo.wmlink.service.impl.DataShowScheduleComputeServiceImpl$$EnhancerBySpringCGLIB$$b9ee37ac.computeAvgIntegrityRate(<generated>) at com.linkyoyo.wmlink.schedule.ComputeDataShowService.computeAllFunction(ComputeDataShowService.java:119) at com.linkyoyo.wmlink.schedule.ComputeDataShowService$$FastClassBySpringCGLIB$$f85885cb.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:748) Caused by: org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:228) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:536) ... 16 common frames omitted
How can I deal this problem? Thanks.
-
liu246437 about 5 yearsYes. I call other service's method in the methodB, and it throws exception. I catch the exception in methodB. So if the other service's method throw the exception, the transaction will be marked by rollback only? You mean I should use the annotation for the method which I called in the methodB?
-
marthursson about 5 yearsYes, the noRollbackFor needs to be placed on the method you call from methodB