欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring的UnexpectedRollbackException事務(wù)嵌套示例解析

 更新時(shí)間:2023年09月13日 09:54:14   作者:codecraft  
這篇文章主要為大家介紹了spring的UnexpectedRollbackException事務(wù)嵌套示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

UnexpectedRollbackException

/**
 * Thrown when an attempt to commit a transaction resulted
 * in an unexpected rollback.
 *
 * @author Rod Johnson
 * @since 17.03.2003
 */
@SuppressWarnings("serial")
public class UnexpectedRollbackException extends TransactionException {
    /**
     * Constructor for UnexpectedRollbackException.
     * @param msg the detail message
     */
    public UnexpectedRollbackException(String msg) {
        super(msg);
    }
    /**
     * Constructor for UnexpectedRollbackException.
     * @param msg the detail message
     * @param cause the root cause from the transaction API in use
     */
    public UnexpectedRollbackException(String msg, Throwable cause) {
        super(msg, cause);
    }
}
UnexpectedRollbackException繼承了TransactionException,一般是事務(wù)嵌套,內(nèi)層事務(wù)拋出了異常,外層事務(wù)給catch住了,然后試圖提交事務(wù)報(bào)錯(cuò)

示例

@Transactional
    public Customer createWithCatch(String name, String email) {
        Customer customer = customerRepository.save(new Customer(name, email));
        try {
            demoService.throwExInTx(0);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return customer;
    }
    // demoService
    @Transactional
    public void throwExInTx(int i) {
        int result = 1 / i;
    }
這里內(nèi)層事務(wù)throwExInTx拋出了異常,而外層事務(wù)createWithCatch給catch住了,最后提交事務(wù)則報(bào)UnexpectedRollbackException異常

源碼解析

invokeWithinTransaction

org/springframework/transaction/interceptor/TransactionAspectSupport.java

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {
        //......
        if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
            // Standard transaction demarcation with getTransaction and commit/rollback calls.
            TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
            Object retVal;
            try {
                // This is an around advice: Invoke the next interceptor in the chain.
                // This will normally result in a target object being invoked.
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // target invocation exception
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
            if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                // Set rollback-only in case of Vavr failure matching our rollback rules...
                TransactionStatus status = txInfo.getTransactionStatus();
                if (status != null && txAttr != null) {
                    retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                }
            }
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }
        //......    
    }
TransactionAspectSupport的invokeWithinTransaction方法在執(zhí)行invocation.proceedWithInvocation()時(shí)會(huì)catch住異常,然后執(zhí)行completeTransactionAfterThrowing

completeTransactionAfterThrowing

org/springframework/transaction/interceptor/TransactionAspectSupport.java

/**
     * Handle a throwable, completing the transaction.
     * We may commit or roll back, depending on the configuration.
     * @param txInfo information about the current transaction
     * @param ex throwable encountered
     */
    protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
        if (txInfo != null && txInfo.getTransactionStatus() != null) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                        "] after exception: " + ex);
            }
            if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                try {
                    txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    throw ex2;
                }
            }
            else {
                // We don't roll back on this exception.
                // Will still roll back if TransactionStatus.isRollbackOnly() is true.
                try {
                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    throw ex2;
                }
            }
        }
    }
completeTransactionAfterThrowing會(huì)判斷該異常是否要rollback,需要rollback的話,則執(zhí)行txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus())

processRollback

org/springframework/transaction/support/AbstractPlatformTransactionManager.java

/**
     * Process an actual rollback.
     * The completed flag has already been checked.
     * @param status object representing the transaction
     * @throws TransactionException in case of rollback failure
     */
    private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
        try {
            boolean unexpectedRollback = unexpected;
            try {
                triggerBeforeCompletion(status);
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Rolling back transaction to savepoint");
                    }
                    status.rollbackToHeldSavepoint();
                }
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction rollback");
                    }
                    doRollback(status);
                }
                else {
                    // Participating in larger transaction
                    if (status.hasTransaction()) {
                        if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                            if (status.isDebug()) {
                                logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                            }
                            doSetRollbackOnly(status);
                        }
                        else {
                            if (status.isDebug()) {
                                logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                            }
                        }
                    }
                    else {
                        logger.debug("Should roll back transaction but cannot - no transaction available");
                    }
                    // Unexpected rollback only matters here if we're asked to fail early
                    if (!isFailEarlyOnGlobalRollbackOnly()) {
                        unexpectedRollback = false;
                    }
                }
            }
            catch (RuntimeException | Error ex) {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                throw ex;
            }
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
            // Raise UnexpectedRollbackException if we had a global rollback-only marker
            if (unexpectedRollback) {
                throw new UnexpectedRollbackException(
                        "Transaction rolled back because it has been marked as rollback-only");
            }
        }
        finally {
            cleanupAfterCompletion(status);
        }
    }
processRollback這里會(huì)判斷,如果該事務(wù)外層還有事務(wù),則判斷status.isLocalRollbackOnly()或者是isGlobalRollbackOnParticipationFailure(默認(rèn)返回true),然后執(zhí)行doSetRollbackOnly(status)

doSetRollbackOnly

org/springframework/orm/jpa/JpaTransactionManager.java

protected void doSetRollbackOnly(DefaultTransactionStatus status) {
        JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction();
        if (status.isDebug()) {
            logger.debug("Setting JPA transaction on EntityManager [" +
                    txObject.getEntityManagerHolder().getEntityManager() + "] rollback-only");
        }
        txObject.setRollbackOnly();
    }
doSetRollbackOnly會(huì)獲取txObject執(zhí)行setRollbackOnly

setRollbackOnly

org/springframework/orm/jpa/JpaTransactionManager.java

public void setRollbackOnly() {
            EntityTransaction tx = getEntityManagerHolder().getEntityManager().getTransaction();
            if (tx.isActive()) {
                tx.setRollbackOnly();
            }
            if (hasConnectionHolder()) {
                getConnectionHolder().setRollbackOnly();
            }
        }
setRollbackOnly這里會(huì)執(zhí)行tx.setRollbackOnly()、getConnectionHolder().setRollbackOnly()標(biāo)記為rollbackOnly

外層事務(wù)processCommit

org/springframework/transaction/support/AbstractPlatformTransactionManager.java

/**
     * Process an actual commit.
     * Rollback-only flags have already been checked and applied.
     * @param status object representing the transaction
     * @throws TransactionException in case of commit failure
     */
    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            boolean beforeCompletionInvoked = false;
            try {
                boolean unexpectedRollback = false;
                prepareForCommit(status);
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked = true;
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Releasing transaction savepoint");
                    }
                    unexpectedRollback = status.isGlobalRollbackOnly();
                    status.releaseHeldSavepoint();
                }
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction commit");
                    }
                    unexpectedRollback = status.isGlobalRollbackOnly();
                    doCommit(status);
                }
                else if (isFailEarlyOnGlobalRollbackOnly()) {
                    unexpectedRollback = status.isGlobalRollbackOnly();
                }
                // Throw UnexpectedRollbackException if we have a global rollback-only
                // marker but still didn't get a corresponding exception from commit.
                if (unexpectedRollback) {
                    throw new UnexpectedRollbackException(
                            "Transaction silently rolled back because it has been marked as rollback-only");
                }
            }
            catch (UnexpectedRollbackException ex) {
                // can only be caused by doCommit
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
                throw ex;
            }
            catch (TransactionException ex) {
                // can only be caused by doCommit
                if (isRollbackOnCommitFailure()) {
                    doRollbackOnCommitException(status, ex);
                }
                else {
                    triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                }
                throw ex;
            }
            catch (RuntimeException | Error ex) {
                if (!beforeCompletionInvoked) {
                    triggerBeforeCompletion(status);
                }
                doRollbackOnCommitException(status, ex);
                throw ex;
            }
            // Trigger afterCommit callbacks, with an exception thrown there
            // propagated to callers but the transaction still considered as committed.
            try {
                triggerAfterCommit(status);
            }
            finally {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
            }
        }
        finally {
            cleanupAfterCompletion(status);
        }
    }
processCommit在unexpectedRollback為true的時(shí)候會(huì)拋出UnexpectedRollbackException(Transaction silently rolled back because it has been marked as rollback-only);這里是status.isGlobalRollbackOnly()被標(biāo)記為true了,因而unexpectedRollback為true

小結(jié)

UnexpectedRollbackException繼承了TransactionException,一般是事務(wù)嵌套,內(nèi)層事務(wù)拋出了異常,外層事務(wù)給catch住了,然后試圖提交事務(wù)報(bào)錯(cuò)UnexpectedRollbackException(Transaction silently rolled back because it has been marked as rollback-only)。

以上就是spring的UnexpectedRollbackException事務(wù)嵌套示例解析的詳細(xì)內(nèi)容,更多關(guān)于spring 事務(wù)嵌套的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot如何使用.yml配置端口號(hào)

    Springboot如何使用.yml配置端口號(hào)

    這篇文章主要介紹了Springboot如何使用.yml配置端口號(hào)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java方法重寫(xiě)時(shí)需要注意的問(wèn)題

    java方法重寫(xiě)時(shí)需要注意的問(wèn)題

    大家好,本篇文章主要講的是java方法重寫(xiě)時(shí)需要注意的問(wèn)題,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Spring cloud Eureka注冊(cè)中心搭建的方法

    Spring cloud Eureka注冊(cè)中心搭建的方法

    這篇文章主要介紹了Spring cloud Eureka注冊(cè)中心搭建的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • java二分查找插入法

    java二分查找插入法

    當(dāng)你需要構(gòu)建一個(gè)大的有序隊(duì)列,用插入發(fā)太慢了,可以先用二分查找法,找到在隊(duì)列要插入的位置,把數(shù)后移一下,然后放進(jìn)去。比較效率,下面是java使用示例,需要的朋友可以參考下
    2014-03-03
  • SpringBoot 使用 FTP 操作文件的過(guò)程(刪除、上傳、下載文件)

    SpringBoot 使用 FTP 操作文件的過(guò)程(刪除、上傳、下載文件)

    這篇文章主要介紹了SpringBoot 使用 FTP 操作文件,主要包括配置ftp服務(wù)器,上傳、刪除、下載文件操作,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • java實(shí)現(xiàn)上傳圖片進(jìn)行切割的方法

    java實(shí)現(xiàn)上傳圖片進(jìn)行切割的方法

    這篇文章主要介紹了java實(shí)現(xiàn)上傳圖片進(jìn)行切割的方法,以完整實(shí)例形式分析了Java針對(duì)上傳圖片進(jìn)行切割的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • springboot2中使用@JsonFormat注解不生效的解決

    springboot2中使用@JsonFormat注解不生效的解決

    這篇文章主要介紹了springboot2中使用@JsonFormat注解不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • springboot的LogbackLoggingSystem配置加載流程解析

    springboot的LogbackLoggingSystem配置加載流程解析

    這篇文章主要介紹了springboot的LogbackLoggingSystem配置加載流程源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Zuul 實(shí)現(xiàn)網(wǎng)關(guān)轉(zhuǎn)發(fā)的五種方式小結(jié)

    Zuul 實(shí)現(xiàn)網(wǎng)關(guān)轉(zhuǎn)發(fā)的五種方式小結(jié)

    這篇文章主要介紹了Zuul 實(shí)現(xiàn)網(wǎng)關(guān)轉(zhuǎn)發(fā)的五種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 利用POI生成EXCEL文件的方法實(shí)例

    利用POI生成EXCEL文件的方法實(shí)例

    Apache POI 是用Java編寫(xiě)的免費(fèi)開(kāi)源的跨平臺(tái)的 Java API,Apache POI提供API給Java程式對(duì)Microsoft Office格式檔案讀和寫(xiě)的功能,下面這篇文章主要給大家介紹了關(guān)于利用POI生成EXCEL文件的相關(guān)資料,需要的朋友可以參考下
    2018-07-07

最新評(píng)論