Transaction rolled back because it has been marked as rollback-only 解决办法

       今天早上高高兴兴上班,居然收到一大堆报警信息,仔细看了一下具体内容,都在提示这个错误

:"Transaction rolled back because it has been marked as rollback-only"

我一看就觉得奇怪了,为什么会有rollback呢,出现问题的地方,就是一个get查询,而且已经标记为readonly=true了。

下面是项目的事务配置:

 
       
           
           
           
           
           
           
           
       

   

 

没毛病啊,根据事务的传播性默认为REQUIRED,就是“没有则新建一个事务,存在则加入当前事务”。但是一个只读的事务,为啥会有回滚呢?

上网查了一下,返现很多有人都有遇到类似的问题。

 

原因:

如果getApply()的方法里面调用了一个load()的方法,同时getApply()捕捉了load()方法的异常而没有抛出,则就会报这个错误“”,如果继续往外抛出这个错误就没有问题了。

这是因为事务默认属性配置都为PROPAGATION_REQUIRED,

所以两方法使用的是同一事务,如果load方法出现异常,则org.springframework.transaction.interceptor.

TransactionInterceptor的invoke处理后则会抛出异常.执行completeTransactionAfterThrowing(txInfo, ex);

 

事务抛出的源码如下:

public final void commit(TransactionStatus status) throws TransactionException {
        if (status.isCompleted()) {
            throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
        }

        DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
        if (defStatus.isLocalRollbackOnly()) {
            if (defStatus.isDebug()) {
                this.logger.debug("Transactional code has requested rollback");
            }
            processRollback(defStatus);
            return;
        }
        if ((!(shouldCommitOnGlobalRollbackOnly())) && (defStatus.isGlobalRollbackOnly())) {
            if (defStatus.isDebug()) {
                this.logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
            }
            processRollback(defStatus);

            if ((status.isNewTransaction()) || (isFailEarlyOnGlobalRollbackOnly())) {
                throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");
            }

            return;
        }

        processCommit(defStatus);
    }

 

 

纠其原理其实很简单,在locad()返回的时候,transaction被设置为rollback-only了,但是getApply()正常消化掉,没有继续向外抛。那么getApply()结束的时候,transaction会执commit操作,但是transaction已经被设置为rollback-only了。

所以会出现这个错误。

调整好问题,找解决方案,问题就出现在propagation="REQUIRED"这个属性上。

标准文档上这样写:

MANDATORY 
          Support a current transaction, throw an exception if none exists.
NESTED 
          Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.
NEVER 
          Execute non-transactionally, throw an exception if a transaction exists.
NOT_SUPPORTED 
          Execute non-transactionally, suspend the current transaction if one exists.
REQUIRED 
          Support a current transaction, create a new one if none exists.
REQUIRES_NEW 
          Create a new transaction, suspend the current transaction if one exists.
SUPPORTS 
          Support a current transaction, execute non-transactionally if none exists.

事务配置参考地址: https://blog.csdn.net/bao19901210/article/details/41724355

怎么办?改成supports:

        

            

        

这个状态用一句话概括就是“有则加入事物,无也不创建事物”。对于只读的方法来说,其实不启用事务,也是没有关系的。

 

参考博客:

https://blog.csdn.net/caolaosanahnu/article/details/6890107

 

你可能感兴趣的:(mark,Database,java,spring,事务)