How to deal the problem "Transaction was marked for rollback only; cannot commit; "?

10,246

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.

Share:
10,246
liu246437
Author by

liu246437

Updated on June 05, 2022

Comments

  • liu246437
    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
    liu246437 about 5 years
    Yes. 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
    marthursson about 5 years
    Yes, the noRollbackFor needs to be placed on the method you call from methodB