上一篇了解的事务的失效问题,本篇讨论事务的传播机制

本文深入探讨了Spring框架中事务传播行为,特别是REQUIRED和REQUIRES_NEW的用法。在场景一中,外围方法无事务时,内部方法各自拥有独立事务;而在开启事务的场景二中,外围方法与内部方法共享事务,任何异常都将导致整体事务回滚。此外,还介绍了NESTED事务传播行为,以及它们在不同情况下的事务管理效果。
摘要由CSDN通过智能技术生成

先来几个例子描述一下spring 默认事务传播机制 Propagation.REQUIRED

@Service
public class User1ServiceImpl implements User1Service {
//省略其他…
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequired(User1 user){
user1Mapper.insert(user);
}
}

@Service
public class User2ServiceImpl implements User2Service {
//省略其他…
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequired(User2 user){
user2Mapper.insert(user);
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequiredException(User2 user){
user2Mapper.insert(user);
throw new RuntimeException();
}

}

1.1 场景一
此场景外围方法没有开启事务。

验证方法1:

@Override
public void notransaction_exception_required_required(){
    User1 user1=new User1();
    user1.setName("张三");
    user1Service.addRequired(user1);
    
    User2 user2=new User2();
    user2.setName("李四");
    user2Service.addRequired(user2);
    
    throw new RuntimeException();
}

验证方法2:

@Override
public void notransaction_required_required_exception(){
    User1 user1=new User1();
    user1.setName("张三");
    user1Service.addRequired(user1);
    
    User2 user2=new User2();
    user2.setName("李四");
    user2Service.addRequiredException(user2);
}

第一种 “张三”、“李四”均插入。 解析: 外围方法未开启事务,插入“张三”、“李四”方法在自己的事务中独立运行,外围方法异常不影响内部插入“张三”、“李四”方法独立的事务。

第二种: “张三”插入,“李四”未插入。 外围方法没有事务,插入“张三”、“李四”方法都在自己的事务中独立运行,所以插入“李四”方法抛出异常只会回滚插入“李四”方法,插入“张三”方法不受影响。

1.2 场景二
外围方法开启事务,这个是使用率比较高的场景。

验证方法1:

@Override
@Transactional(propagation = Propagation.REQUIRED)
public void transaction_exception_required_required(){
User1 user1=new User1();
user1.setName(“张三”);
user1Service.addRequired(user1);

    User2 user2=new User2();
    user2.setName("李四");
    user2Service.addRequired(user2);
    
    throw new RuntimeException();
}

验证方法2:

@Override
@Transactional(propagation = Propagation.REQUIRED)
public void transaction_required_required_exception(){
    User1 user1=new User1();
    user1.setName("张三");
    user1Service.addRequired(user1);
    
    User2 user2=new User2();
    user2.setName("李四");
    user2Service.addRequiredException(user2);
}

验证方法3:

@Transactional
@Override
public void transaction_required_required_exception_try(){
    User1 user1=new User1();
    user1.setName("张三");
    user1Service.addRequired(user1);
    
    User2 user2=new User2();
    user2.setName("李四");
    try {
        user2Service.addRequiredException(user2);
    } catch (Exception e) {
        System.out.println("方法回滚");
    }
}

验证方法一 “张三”、“李四”均未插入。 解析: 外围方法开启事务,内部方法加入外围方法事务,外围方法回滚,内部方法也要回滚。

验证方法二 “张三”、“李四”均未插入。 解析: 外围方法开启事务,内部方法加入外围方法事务,内部方法抛出异常回滚,外围方法感知异常致使整体事务回滚。

验证方法三 “张三”、“李四”均未插入。 解析: 外围方法开启事务,内部方法加入外围方法事务,内部方法抛出异常回滚,即使方法被catch不被外围方法感知,整个事务依然回滚。 就是try catch了也是回滚的

其他几种事务传播:

一:Propagation.REQUIRES_NEW 在外围方法未开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。 在外围方法开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。

二: Propagation.NESTED 在外围方法未开启事务的情况下Propagation.NESTED和Propagation.REQUIRED作用相同,修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。 在外围方法开启事务的情况下Propagation.NESTED修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值