Spring-TX-Propagation-事务传播行为

【Spring】事务和事务的传播机制 将一组操作封装在一起执行,要么全部成功,要么全部失败。 阅读详情

Spring-Tx

传播行为

propagation提交异常捕获后异常
required (rollbackOnly)do nothing / commitsetRollbackOnly / rollbacksetRollbackOnly / rollback
required_new (isNewTransaction)commit / commitrollback / rollbackrollback / commitcommit / rollback
nested (savePoint)releaseSavepoint / commitrollbackToSavepoint & releaseSavepoint / rollbackrollbackToSavepoint & releaseSavePoint / commit

REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
本质上是同一个事务
提交:什么也不做
异常传递:rollbackOnly = true
异常捕获:rollbackOnly = true

REQUIRED_NEW

新建事务,如果当前存在事务,把当前事务挂起。
提交:isNewTx = true 提交
异常传递:rollback / rollback
异常捕获:rollback / commit
异常后捕:commit / rollback
A、B不可操作同一条记录,因为处于不同事务中,会产生死锁。

NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
提交:releaseSavepoint / commit 
异常传递:rollbackToSavepoint & releaseSavepoint / rollback
异常捕获:rollbackToSavepoint & releaseSavepoint / commit
A、B可操作同一条记录,因为处于同一个事务中。

SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。
提交:
异常捕获:
异常传递:

MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。
提交:
异常捕获:
异常传递:

NOT_SUPPORTS

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
提交:
异常捕获:
异常传递:

NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。
提交:
异常捕获:
异常传递:

核心代码-AOP

    // Standard transaction demarcation with getTransaction and commit/rollback calls.
    TransactionInfo txInfo = createTransactionIfNecessary(tm,txAttr,joinpointIdentification);
    Object retVal = null;
    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);
    }
    commitTransactionAfterReturning(txInfo);
    return retVal;

回滚事务

    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 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");
            }
        }
    }

提交事务-01

    DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
    if (defStatus.isLocalRollbackOnly()) {
        if (defStatus.isDebug()) {
            logger.debug("Transactional code has requested rollback");
        }
        processRollback(defStatus);
        return;
    }
    if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
        if (defStatus.isDebug()) {
            logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
        }
        processRollback(defStatus);
        // Throw UnexpectedRollbackException only at outermost transaction boundary
        // or if explicitly asked to.
        if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
            throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");
        }
        return;
    }
    
    processCommit(defStatus);

提交事务-02

    if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
        globalRollbackOnly = status.isGlobalRollbackOnly();
    }
    if (status.hasSavepoint()) {
        if (status.isDebug()) {
            logger.debug("Releasing transaction savepoint");
        }
        status.releaseHeldSavepoint();
    }
    else if (status.isNewTransaction()) {
        if (status.isDebug()) {
            logger.debug("Initiating transaction commit");
        }
        doCommit(status);
    }

测试代码

package center.leon.springtx;

import center.leon.springtx.service.TxAService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.event.TransactionalEventListenerFactory;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
import org.springframework.transaction.interceptor.TransactionInterceptor;

@Slf4j
@EnableTransactionManagement
@SpringBootApplication
public class SpringTxApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(SpringTxApplication.class, args);

        // 基础增强自动代理创建器
        final InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator = run.getBean(InfrastructureAdvisorAutoProxyCreator.class);
        assert null != infrastructureAdvisorAutoProxyCreator;
        // TransactionalEventListener : https://blog.youkuaiyun.com/qq_41378597/article/details/105748703
        final TransactionalEventListenerFactory transactionalEventListenerFactory = run.getBean(TransactionalEventListenerFactory.class);
        assert null != transactionalEventListenerFactory;
        //
        final AnnotationTransactionAttributeSource annotationTransactionAttributeSource = run.getBean(AnnotationTransactionAttributeSource.class);
        assert null != annotationTransactionAttributeSource;
        // 事务AOP增强
        final TransactionInterceptor transactionInterceptor = run.getBean(TransactionInterceptor.class);
        assert null != transactionInterceptor;
        //
        final BeanFactoryTransactionAttributeSourceAdvisor beanFactoryTransactionAttributeSourceAdvisor = run.getBean(BeanFactoryTransactionAttributeSourceAdvisor.class);
        assert null != beanFactoryTransactionAttributeSourceAdvisor;

        final TxAService txAService = run.getBean(TxAService.class);
        txAService.truncateTable();
        /**
         *
         */
        txAService.required_commit_NoTx_commit();
        /**
         *
         */
        try {
            txAService.required_commit_NoTx_Ex();
        } catch (Exception e) {
        }
        /**
         * commit / commit
         */
        txAService.required_commit_Required_commit();
        /**
         * setRollbackOnly / rollback
         */
        try {
            txAService.required_commit_Required_Ex();
        } catch (Exception e) {
        }
        /**
         * setRollbackOnly / rollback
         */
        try {
            txAService.required_commit_Required_Ex_Caught();
        } catch (Exception e) {
        }
        /**
         * commit / commit
         */
        txAService.required_commit_Required_New_Commit();
        /**
         * rollback / commit
         */
        try {
            txAService.required_commit_Required_New_Ex();
        } catch (Exception e) {
        }
        /**
         * rollback / commit
         */
        txAService.required_commit_Required_New_Ex_Caught();
        /**
         * commit / rollback
         */
        try {
            txAService.required_Ex_Required_New_commit();
        } catch (Exception e) {
        }
        /**
         * releaseSavePoint / commit
         */
        txAService.required_commit_Required_Nested_Commit();
        /**
         * rollbackToSavePoint & releaseSavePoint / rollback
         */
        try {
            txAService.required_commit_Required_Nested_Ex();
        } catch (Exception e) {
        }
        /**
         * rollbackToSavePoint & releaseSavePoint / commit
         */
        txAService.required_commit_Required_Nested_Ex_Caught();
        /**
         * THIS 以下
         */
        txAService.required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid();
        /**
         * Spring 以下
         */
        txAService.required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid();
        System.out.println("天地英雄气,千秋尚凛然");
    }

}

ServiceA Interface

package center.leon.springtx.service;

/**
 * Description:
 *
 * @author Leon
 * @since 2022/1/11 1:57 下午
 */
public interface TxAService {

    void truncateTable();

    void required_commit_NoTx_commit();

    void required_commit_NoTx_Ex();

    void required_commit_Required_commit();

    void required_commit_Required_Ex();

    void required_commit_Required_Ex_Caught();

    void required_commit_Required_New_Commit();

    void required_commit_Required_New_Ex();

    void required_commit_Required_New_Ex_Caught();

    void required_Ex_Required_New_commit();

    void required_commit_Required_Nested_Commit();

    void required_commit_Required_Nested_Ex();

    void required_commit_Required_Nested_Ex_Caught();

    // this 以下是
    void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid();

    void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this(String name);

    // Spring 以下是
    void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid();

    void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring(String name);
}

ServiceAImpl Class

package center.leon.springtx.service.impl;

import center.leon.springtx.dao.MonkeyDao;
import center.leon.springtx.mapper.MonkeyMapper;
import center.leon.springtx.service.TxAService;
import center.leon.springtx.service.TxBService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * Description:
 *
 * @author Leon
 * @since 2022/1/11 1:57 下午
 */
@Service
@Slf4j
public class TxAServiceImpl implements TxAService {

    @Autowired
    private TxBService txBService;
    @Autowired
    private MonkeyDao monkeyDao;
    @Autowired
    private MonkeyMapper monkeyMapper;

    @Autowired
    private TxAService txAService;

    @Override
    public void truncateTable() {
        monkeyMapper.truncateTable();
    }

    /**
     * A 开启事务 ts(isNewTx = true)
     * B TransactionInterceptor 不拦截,无事务增强
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_NoTx_commit() {
        monkeyDao.insert("required_commit_NoTx_commit_A");
        txBService.required_commit_NoTx_commit("required_commit_NoTx_commit_B");
    }

    /**
     * A 开启事务 ts(isNewTx = true)
     * B TransactionInterceptor 不拦截,无事务增强
     * B 抛异常,捕获异常,向上传递。
     * 在 A catch 处理程序中 根据 rollbackFor 配置决定是否回滚或提交
     * 回滚:A ts(isNewTx = true) 回滚。继续抛出 异常。
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_NoTx_Ex() {
        monkeyDao.insert("required_commit_NoTx_Ex_A");
        txBService.required_commit_NoTx_Ex("required_commit_NoTx_Ex_B");
    }

    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)
     * B 提交事务 ts(isNewTx = false),不 commit
     * A 开启事务 ts(isNewTx = true),commit
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_commit() {
        monkeyDao.insert("required_commit_Required_commit_A");
        txBService.required_commit_Required_commit("required_commit_Required_commit_B");
    }


    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)
     * B 抛异常
     * 在 B catch 处理程序中 根据 rollbackFor 配置决定是否回滚或提交
     * 回滚:B ts(isNewTx = false, ConnectionHolder::rollbackOnly = true), 继续抛出异常
     * 提交:
     * 在 A catch 处理程序中 根据 rollbackFor 配置决定是否回滚或提交
     * 回滚:A ts(isNewTx = true, ConnectionHolder::rollbackOnly = true), 执行回滚逻辑。继续抛出异常
     * 提交:
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Ex() {
        monkeyDao.insert("required_commit_Required_Ex_A");
        txBService.required_commit_Required_Ex("required_commit_Required_Ex_B");
    }

    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)
     * B 抛异常
     * 在 B catch 处理程序中 根据 rollbackFor 配置决定是否回滚或提交
     * 回滚:B ts(isNewTx = false, ConnectionHolder::rollbackOnly = true), 继续抛出异常
     * 提交:
     * 在 A catch 处理程序中 根据 rollbackFor 配置决定是否回滚或提交
     * 回滚:A ts(isNewTx = true, ConnectionHolder::rollbackOnly = true), 执行回滚逻辑。继续抛出异常
     * 提交:
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Ex_Caught() {
        monkeyDao.insert("required_commit_Required_Ex_Caught_A");
        try {
            txBService.required_commit_Required_Ex_Caught("required_commit_Required_Ex_Caught_B");
        } catch (Exception e) {
            log.info("required_commit_Required_Ex_Caught_B. error : {}", e.getMessage(), e);
        }
    }


    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)(线程挂起资源时,清除connect。重新获取ts(isNewTx = true),开启事务,重新获取connect)
     * 提交:B con.commit();
     * 提交:A con.commit();
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_New_Commit() {
        monkeyDao.insert("required_commit_Required_New_Commit_A");
        txBService.required_commit_Required_New_Commit("required_commit_Required_New_Commit_B");
    }


    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)(线程挂起资源时,清除connect。重新获取ts(isNewTx = true),开启事务,重新获取connect)
     * 回滚:B con.rollback(); 继续向上传递异常
     * 回滚:A con.rollback(); 继续向上传递异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_New_Ex() {
        monkeyDao.insert("required_commit_Required_New_Ex_A");
        txBService.required_commit_Required_New_Ex("required_commit_Required_New_Ex_B");
    }


    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)(线程挂起资源时,清除connect。重新获取ts(isNewTx = true),开启事务,重新获取connect)
     * 提交:B con.commit();
     * 回滚:A con.rollback(); 继续向上传递异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_New_Ex_Caught() {
        monkeyDao.insert("required_commit_Required_New_Ex_Caught_A");
        try {
            txBService.required_commit_Required_New_Ex_Caught("required_commit_Required_New_Ex_Caught_B");
        } catch (Exception e) {
            log.info("required_commit_Required_New_Ex_Caught_B : {}", e.getMessage(), e);
        }
    }


    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false)(线程挂起资源时,清除connect。重新获取ts(isNewTx = true),开启事务,重新获取connect)
     * 提交:B con.commit();
     * 回滚:A con.rollback(); 继续向上传递异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_Ex_Required_New_commit() {
        monkeyDao.insert("required_Ex_Required_New_commit_A");
        txBService.required_Ex_Required_New_commit("required_Ex_Required_New_commit_B");
        int i = 0 / 0;
    }


    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false, crateAndHoledSavePoint())
     * 提交:B release savePoint
     * 提交:A con.commit();
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Nested_Commit() {
        monkeyDao.insert("required_commit_Required_Nested_Commit_A");
        txBService.required_commit_Required_Nested_Commit("required_commit_Required_Nested_Commit_B");
    }

    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false, crateAndHeldSavePoint())
     * 回滚:B rollbackTo/release savePoint 继续向上传递异常
     * 回滚:A con.rollback();
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Nested_Ex() {
        monkeyDao.insert("required_commit_Required_Nested_Ex_A");
        txBService.required_commit_Required_Nested_Ex("required_commit_Required_Nested_Ex_B");
    }

    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * B 开启事务 ts(isNewTx = false, crateAndHeldSavePoint())
     * 回滚:B rollbackTo/release savePoint (ConnectionHolder:rollbackOnly still is false) 继续向上传递异常
     * A catch B ex
     * 提交:A con.rollback();
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Nested_Ex_Caught() {
        monkeyDao.insert("required_commit_Required_Nested_Ex_Caught_A");
        try {
            txBService.required_commit_Required_Nested_Ex_Caught("required_commit_Required_Nested_Ex_Caught_B");
        } catch (Exception e) {
            log.info("required_commit_Required_Nested_Ex_Caught_B. error : {}", e.getMessage(), e);
        }
    }

    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * this.方法名调用是对象内部方法调用,不会通过Spring代理,不会被TransactionInterceptor事务拦截器增强,也就是事务不会起作用。
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid() {
        monkeyDao.insert("required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_A");
        this.required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this("required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this");
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NEVER)
    public void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this(String name) {
        monkeyDao.insert(name);
    }

    /**
     * A 开启事务 ts(isNewTx = true)(线程不带connect)
     * Spring 开启事务 ts(isNewTx = false)
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid() {
        monkeyDao.insert("required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_A");
        txAService.required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring("required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring");
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NEVER)
    public void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring(String name) {
        monkeyDao.insert(name);
    }

}

ServiceB Interface

package center.leon.springtx.service;

/**
 * Description:
 *
 * @author Leon
 * @since 2022/1/11 1:57 下午
 */
public interface TxBService {

    void required_commit_NoTx_commit(String name);

    void required_commit_NoTx_Ex(String name);

    void required_commit_Required_commit(String name);

    void required_commit_Required_Ex(String name);

    void required_commit_Required_Ex_Caught(String name);

    void required_commit_Required_New_Commit(String name);

    void required_commit_Required_New_Ex(String name);

    void required_commit_Required_New_Ex_Caught(String name);

    void required_Ex_Required_New_commit(String name);

    void required_commit_Required_Nested_Commit(String name);

    void required_commit_Required_Nested_Ex(String name);

    void required_commit_Required_Nested_Ex_Caught(String name);
       
}

ServiceBImpl Class

package center.leon.springtx.service.impl;

import center.leon.springtx.dao.MonkeyDao;
import center.leon.springtx.service.TxBService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * Description:
 *
 * @author Leon
 * @since 2022/1/11 1:57 下午
 */
@Service
public class TxBServiceImpl implements TxBService {

    @Autowired
    private MonkeyDao monkeyDao;

    @Override
    public void required_commit_NoTx_commit(String name) {
        monkeyDao.insert(name);
    }

    @Override
    public void required_commit_NoTx_Ex(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_commit(String name) {
        monkeyDao.insert(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Ex(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void required_commit_Required_Ex_Caught(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void required_commit_Required_New_Commit(String name) {
        monkeyDao.insert(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void required_commit_Required_New_Ex(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void required_commit_Required_New_Ex_Caught(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void required_Ex_Required_New_commit(String name) {
        monkeyDao.insert(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void required_commit_Required_Nested_Commit(String name) {
        monkeyDao.insert(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void required_commit_Required_Nested_Ex(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void required_commit_Required_Nested_Ex_Caught(String name) {
        monkeyDao.insert(name);
        int i = 0 / 0;
    }
}
Spring 事务和事务传播机制 阅读详情

相关推荐

Spring事务传播:Propagation.REQUIRES_NEW、NEVER和MANDATORY的验证及失效问题

本文将重点介绍Spring事务传播的三种行为:Propagation.REQUIRES_NEW、Propagation.NEVER和Propagation.MANDATORY,并探讨可能导致这些传播行为失效的诡异问题。在同一个类中的方法内部直接调用另一个使用了事务传播行为的方法时,传播行为可能会失效。在同一个类中的非事务方法调用了一个使用了事务传播行为的方法时,传播行为可能会失效。为了解决这个问题,可以将非事务方法移到另一个类中,或者在非事务方法上添加事务注解以启动一个新的事务。4.3. 异步方法问题。

JoplCommon的博客 1009

Spring 事务的传播机制

Spring 事务的传播机制演示, 包含 REQUIRED、REQUIRES_NEW 以及嵌套式事务详解

这个人很懒, 什么都没留下(这是我写的) 6661

Unity 调用安卓内部安装apk

一、申请权限 应用内安装其他应用的权限属于特殊权限,需要在特殊申请。 Uri packageURI = Uri.parse("package:" + mContext.getPackageName()); Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI); startA...

BDDNH的博客 1238

【Spring】Spring的7种事务传播机制讲解,以及49种组合方式介绍

Spring的7种事务传播机制讲解,以及49种组合方式介绍

zxy2361380031的博客 1万+

SAP ABAP MIGO增强实战:自定义页签与字段的完整实现指南

本文详细介绍了SAP ABAP中MIGO增强的实战指南,包括自定义页签与字段的完整实现步骤。通过BADI增强技术,开发者可以快速满足企业个性化需求,如添加供应商批次号等特殊字段。文章涵盖数据存储结构设计、BADI框架实现、核心方法编写及数据持久化方案,帮助用户高效完成MIGO屏幕增强开发。

study的专栏 773

基因家族扩张收缩分析可视化(CAFE5)

CafePlotter 是一个用于可视化 CAFE5 基因家族扩张收缩分析结果的 Python 工具

xuzhougeng blog 3627

Spring事务通知tx:advice标签

spring配置文件样例 简单的事务配置,对save/delete开头的方法加事务,get/find开头的设置为不加事务只读模式 <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method n...

beastars1的博客 685

【A_Star三维路径规划】基于matlab A_Star算法结合B样条平滑三维地形路径规划(含雷达威胁)【含Matlab源码 3527期】

A_Star算法结合B样条平滑三维地形路径规划(含雷达威胁) 完整代码,包运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 740

spring 配置文件中的propagation的7种配置的意思

下面是Spring中Propagation类的事务属性详解: REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。 MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。 REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。 NOT_SUPPORTED:以非事务方式执...

xipixi4802的博客 305

订餐平台餐厅信息抓取:使用Python爬虫获取商家信息和用户评价

在这篇博客中,我们展示了如何使用Python爬虫抓取订餐平台上的餐厅信息和用户评价数据。通过使用requests和Selenium,我们能够有效地从静态和动态网页中提取数据,并使用pandas和matplotlib对数据进行存储和分析。未来,您可以根据需求进一步扩展功能,例如增加错误处理、增加抓取多个页面的能力,或者使用高级技术如分布式爬虫来抓取更大规模的数据。

2201_76125261的博客 1650

2 硬件工程师笔面试高频知识考点真题解析——电容

本文全面解析了电容在电子电路中的关键应用与技术要点。主要内容包括:1. 电容选型核心要素:介质材质(陶瓷/电解/钽电容等)、容值精度、耐压等级、温度特性、ESR参数等,不同应用场景(滤波/去耦/谐振等)的选型策略。2. 典型电路应用原理:详细阐述去耦电容布局规则、晶振负载电容作用、共射放大电路旁路电容功能,以及RC电路的滤波/定时等应用。3. 特殊问题解决方案:MLCC啸叫机理与对策、寄生电容影响与消除、高速信号线电容使用禁忌等工程实践难题。4. 安全规范要点:X/Y电容的区别与选用、电解/钽电容防反接措施

XU157303764的博客 1556

spring in action学习笔记 5 事务中参数的一些汇总

事务创建时或者是现有事务可以使用所定义的传播规则 Spring提供几种传播规则供选择 [b]1.传播行为[/b] PROPAGATION_MANDATORY:表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常。 PROPAGATION_NESTED:表示如果当前正由一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚...

DoubleEO---爱就是性,性就是死 131

极智芯 | 解读国产CPU之海光

大家好,我是极智视界,本文分享一下 解读国产CPU之海光。希望我的分享能对你的学习有一点帮助。

极智视界 3316

Spring对事务配置的五种方式和事务的传播属性和隔离级别

这应该是自己第一次认真的写博客,驱动自己写这个博客的原因如下:1、工作这么久,都会把自己的积累以网页的形式放到硬盘中,分类不清晰,查找更不方便,如果数据丢失,这些经验有可能会白费。2、面试的经历让自己明白,不仅要明白大致过程,还要理解具体细节,而自己看的虽然多,但是真正描述的时候却不清晰,为了摆脱这,所以以写博客的方式来增强记忆。好了,不说那么多,希望自己能坚持下来。接下来就描述下Spring对事

zfc5840的专栏 880

dolphinscheduler集群服务一键安装启动实现流程剖析

通过以上分析我们基本梳理清楚了整个dolphinscheduler项目的一键安装启动逻辑, 我们现在在通过一张图正好理一下整个实现流程。关于一键停止集群服务及一件查询集群各个角色服务实例运行状态的实现也都在stop-all.sh/status-all.sh及dolphinscheduler-daemon.sh这三个脚本中, 有兴趣自行研究。写这篇文章的核心目的不仅在于给大家分享如何优秀的开源项目的一键安装部署的实现过程。

最爱嫣夜来 1207

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Spring的事务管理

但是需要注意的是,这时的事务并没有进行提交,如果后续的代。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回。在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务。事务超时就是事务的一个定时器,在特定时间内事务如果没。可以发现这个接口描述的是一些处理事务提供简单的控制事务执行和查询事务状态的方法,在回滚或提。提供了对编程式事务和声明式事务的支持,编程式事务允许用户在代码中精确定义事务的边界,

2301_77822280的博客 232

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

SSM整合

1、tx:method的属性 属性:propagation 类型:Propagation、枚举 默认值:REQUIRED 说明:事务传播属性 属性:isolation类型: isolation、枚举 默认值:DEFAULT(所用数据库默 认级别) 说明:事务隔离级别 属性:readOnly类型: boolean 默认值:false 说明:是否采用优化的只读事务 属性:timeout类型: int默认值:-1说明:超时(秒) 属性:rollbackFor类型: Class[] 默认值:{}说明:需要回滚的异常

weixin_49866322的博客 128

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SSM整合(二)

开发工具与关键技术:IDEA与java语言 作者:陈鑫鹏 撰写时间:2021年9月17日 1、<tx:method >的属性 propagation属性的7个传播行为 REQUIRED:指定当前方法必需在事务环境中运行,如果当前有事务环境就加入当前正在执行的事 务环境,如果当前没有事务,就新建一个事务。这是默认值。 SUPPORTS:指定当前方法加入当前事务环境,如果当前没有事务,就以非事务方式执行。 MANDATORY:指定当前方法必须加入当前事务环境,如果当前没有事务,就抛出异常。

weixin_47799089的博客 117

seata源码分析

进入handleGlobalTransaction这个方法后,它会去记录事物注解的信息,创建TransactionInfo信息,然后点进去excute方法,这里就是事物的一个传播行为的控制。PROPAGATION_REQUIRED: 如果当前没有事务, 就创建一个新事务, 如果当前存在事务, 就加入该事务, 该设置是最常用的设置。PROPAGATION_SUPPORTS: 支持当前事务, 如果当前存在事务, 就加入该事务, 如果当前不存在事务, 就以非事务执行。

users24146的博客 361

spring项目中如何添加事务_Spring中事务的传播行为

当我们在spring中调用Service中一个方法时,如果我们默认配置了对Service的事务管理,那么此时的Service将运行在一个由spring管理的事务环境中。由于在我们日常的开发时,通常会在一个Service接口中调用其它Service中的接口以此来完成一个完整的事务操作,这时就会发生服务接口嵌套调用的情况,spring通过事务传播行为控制当前事务如何传播到被嵌套调用的目标服务接口方法中...

weixin_31458459的博客 1047

Spring事务理解和配置

文章目录1 Spring事务1.1 事务简介1.1.1 什么是事务1.1.2 事物的特性1.1.3 不考虑事物会引发的安全问题1.1.4 事务隔离级别1.2 事务的传播行为1.3 编程式事务(需要手动写代码,了解)1.3.1 配置平台事务管理器1.3.2 Spring提供了事务管理的模板类1.3.3 在业务层注入事务管理的模板1.3.4 编写事务管理的代码1.4 声明式事务(xml配置)1.4.1 配置事务管理器1.4.2 配置增强1.4.3 AOP的配置1.5 声明式事务(注解)1.5.1 配置事务管理器

Student108的博客 2844

【转】Spring中 PROPAGATION_REQUIRED 解释(JAVA事务)

事务传播行为种类 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播: 事务传播行为类型 事务传播行为类型 说明 PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入...

sinat_18474835的博客 1136

Spring 事务

事务是一个整体,内部包含了一批SQL语句,事务提交要么都成功,要么都失败,事务也可以执行回滚 Spring提供事务平台管理器:PlatFormTransationManager,可以实现对各个框架进行事务管理操作 1. 事务的四大特性:ACID 1.1 原子性(Atomicity),事务是一个整体,不可再分,事务操作要么都成功,要么都失败 1.2 一致性(Consistency):数据不会因为事务...

weixin_45874909的博客 145

12、Spring:声明式事务

文章目录回顾事务事务的隔离级别测试导包编写配置文件编写实体类CountsDao接口的实现类CountsDaoImpl编写CountsService接口Spring中的事务管理 回顾事务 事务四个属性ACID 原子性(atomicity) 事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用 一致性(consistency) 一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中 隔离性(isolation) 可能多个事务会同时处理相同

Surplus.的博客 143

第十四章 Spring4 切面事物与事物通知与传播行为

配置事务切面: [code="java"] [/code] 事务传播行为: Spring 中,当一个 service 方法调用另外一个 service 方法的时候,因为每个 service 方法都有事 务,这时候就出现了事务的嵌套;由此,就产生了事务传播行为; 在 S...

fxyyshi的博客 125

spring事务管理

关于事物隔离级别, 脏读, 不可重复读, 幻读的理解, 另有一篇文章比较生动的介绍:http://blog.youkuaiyun.com/sunxing007/article/details/6427290 spring事务管理相关的接口:  TransactionDefinition:代表一个事物,描述了事务的隔离级别, 超时时间,事务是否只读, 传播规则等等; TransactionStatus

LeoYoung 719
上一篇: 菜单目录-行转树
下一篇: Java线程池ThreadPoolExecutor使用和分析(一)
limeOracle
博客等级 码龄10年 11粉丝 566原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值