spring源码事务一传播机制之基础

一.了解spring事务的传播机制

传播机制的定义

REQUIRED 如果当前没有事务,则自己新建一个事;如果当前存在事务,则加入这个事务

REQUIRES_NEW 如果当前没有事务,创建一个新事务;如果存在事务,则挂起该事务,并且新建事务

SUPPORTS 如果当前没有事务,就以非事务方法执行 ;当前存在事务,则加入当前事务,

MANDATORY 如果当前没有事务,则抛出异常;当前存在事务,则加入当前事务

NOT_SUPPORTED 始终以非事务方式执行,如果当前存在事务,则挂起当前事务

NEVER 不使用事务,如果当前事务存在,则抛出异常

NESTED 如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)

NESTED和REQUIRES_NEW的区别: REQUIRES_NEW是新建一个事务并且新开启的这个事务与原有事务无关,而NESTED则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务)。在NESTED情况下父事务回滚时,子事务也会回滚,
而在REQUIRES_NEW情况下,原有事务回滚,不会影响新开启的事务。

NESTED和REQUIRED的区别:
REQUIRED情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用方出现异常时,由于共用一个事务,所以无论调用方是否catch其异常,事务都会回滚而在NESTED情况下,被调用方发生异常时,调用方可以catch其异常,这样只有子事务回滚,父事务不受影响

传播机制的介绍

如果能理解上面关于事务传播的定义,下面的内容可以跳过,接下来我带你们了解一下事务的传播机制

上伪代码喽

public void insertA(Data data){
    //向表a插入数据
}

public void insertB(Data data){
    //更新表b的数据
}

REQUIRED

1.如果当前已经存在事务,加入这个事务

当前情形仍然适用于SUPPORTS,MANDATORY

@Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRED )
public void test(){
 insertA(a);
 try{
    testB()}catch(Exception e){
    }
}

//@Transactional(rollbackFor = Exception.class,propagation= Propagation.MANDATORY )
//@Transactional(rollbackFor = Exception.class,propagation= Propagation.SUPPORTS )
@Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRED )
public void testB(){
   insertB(b);
   throw new NullPointerException()insertB(c);
}

数据a,b, c都属于一个事务, 要么全部回滚(数据库保持原样),要么全部提交(a,b入库)

DataSourceTransactionManager platformTransactionManager = new DataSourceTransactionManager();

//GlobalRollbackOnParticipationFailure如果为false 部分失败不回滚
//GlobalRollbackOnParticipationFailure如果为false 部分失败回滚
platformTransactionManager.setGlobalRollbackOnParticipationFailure(false);
2.如果当前不存在事务,新建事务

当前情形仍然适用于 REQUIRES_NEW,NESTED

public void test(){
 insertA(a);
 try{
    testB()}catch(Exception e){
    }
}

//@Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRES_NEW )
//@Transactional(rollbackFor = Exception.class,propagation= Propagation.NESTED)
@Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRED )
public void testB(){
   insertB(b);
   throw new NullPointerException()insertB(c);
}

1.执行a的入库(没有事务管理)=>a入库sql语句自动提交,直接入库成功

2.执行testB的时候会创建事务,管理b和c的入库,由于b执行完成抛出空指针异常,事务回滚,因此b入库失败

最终结果:只有a入库成功

REQUIRES_NEW

如果当前已经存在事务,新建事务
@Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRED )
public void test() {
    insertA(a);
    testB();
    throw new NullPointerException();
}
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void testB() {
    updateB(b);
    updateB(c);
}

1.创建事务A 事务A执行a的入库

2.执行testB的时候会挂起事务A并创建事务B,执行b和c的入库,提交事务B,恢复事务A

3.抛出异常,事务A回滚,也就是a并未真正入库

最终结果:b,c入库

NOT_SUPPORTED

如果当前存在事务,则挂起当前事务
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void test() {
    insertA(a);
    testB();
}

@Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
public void testB() {
    updateB(b);
    throw new NullPointerException();
    updateB(c);
}

1.执行test的时候会创建事务A,管理a入库

2.执行testB的时候会挂起事务A,testB以非事务运行,b的入库语句自动提交,恢复事务A

3.方法testB抛出异常,并传递给方法test(),事务A回滚

最终结果:b入库

如果当前不存在事务,以非事务方式运行

SUPPORTS也适用于当前案例

public void test() {
    insertA(a);
    testB();
}

//@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
public void testB() {
    updateB(b);
    throw new NullPointerException();
    updateB(c);
}
}

这个效果和没有加@Transation注解一样的,a,b,c的入库都没有事务管理

最终结果:a,b入库

NESTED

//@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void test() {
   insertA(a);
   try{
   testB();
   }catch(Exception e){
   
   }
}

@Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
public void testB() {
   updateB(b);
   throw new NullPointerException();
   updateB(c);
}
}

1.创建事务A,执行a的入库

2.从事务A创建子事务B,管理b和c的入库,在入库之前抛出异常,子事务回滚,子事务B回滚不会影响父事务A

3.事务A入库提交

4.最终结果:a入库

//@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void test() {
   insertA(a);
   testB();
   throw new NullPointerException();
}

@Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
public void testB() {
   updateB(b);
   updateB(c);
}
}

1.创建事务A,执行a的入库

2.从事务A创建子事务B,事务B管理b和c的入库

3.抛出异常,父事务A要回滚,子事务B也需要回滚

4.最终结果:无数据入库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值