Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 770
liu246437 Avatar asked Mar 13 '19 06:03

liu246437


People also ask

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.

What means rollback only?

However, the application should not attempt to rollback the transaction directly. Instead, it should mark the transaction for rollback only, which sets a flag on the transaction indicating that the transaction cannot be committed.


1 Answers

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.

like image 114
marthursson Avatar answered Oct 13 '22 06:10

marthursson