spring事务传播机制之《REQUIRED》

spring事务传播指一个service方法调用多个其他service的方法时事务的范围。即各个被调用的方法和调用者之间怎样处理数据库事务。

spring中共有七中事务类型:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED

本文将举例说明REQUIRED传播类型。

REQUIRED如果当前(上层调用者方法)没有事务,则自己新建一个事务,如果当前(上层调用者方法)存在事务,则加入这个事务spring默认使用该传播类型。

示例一:

// serviceA
@Transactional(propagation = Propagation.REQUIRED)
public void insertA() {
  mapperA.insert()
}

// serviceB
@Transactional(propagation = Propagation.REQUIRED)
public void insertB() {
  mapperB.insert();
  throw new RuntimeException("抛出异常")    // 此处抛出异常类型需为RuntimeException(运行时异常)或子类才会实现事务的回滚,Exception并不会回滚
}

// serviceC
@Transactional(propagation = Propagation.REQUIRED)
public void insertC() {
  mapperC.insert();
}

public void test() {
  this.insertC();        // 此处并不会开启事务,spring事务最终使用的是AOP实现,这里this为serviceC对象,并不会被代理,所以@Transactional不会生效
  serviceA.insertA();    // 开启事务A
  serviceB.insertB();    // 开启事务B
}

在该示例中由于调用者方法中没有事务,所以serviceA.insertA()开启了事务A,serviceB.insertB()开启了事务B,

两个方法分别在两个事务中执行,A添加成功,B被回滚。

示例二

// serviceA
@Transactional(propagation = Propagation.REQUIRED)
public void insertA() {
  mapperA.insert()
}

// serviceB
@Transactional(propagation = Propagation.REQUIRED)
public void insertB() {
  mapperB.insert()
  throw new RuntimeException("抛出异常")
}

// serviceC
@Transactional(propagation = Propagation.REQUIRED)
public void insertC() {
  mapperC.insert()
}

@Transactional(propagation = Propagation.REQUIRED)
public void test() {    // 开启事务A
  serviceA.insertA()    // 加入事务A
  serviceB.insertB()    // 加入事务A
}

在该示例中调用者方法开启了事务A,由于上层方法存在事务,所以serviceA.insertA()和serviceB.insertB()方法都加入了事务A,两个方法都被回滚。

示例三

// serviceA
public void insertA() {
  mapperA.insert()
}

// serviceB
@Transactional(propagation = Propagation.REQUIRED)
public void insertB() {
  mapperB.insert()
  throw new RuntimeException("抛出异常")
}

// serviceC
@Transactional(propagation = Propagation.REQUIRED)
public void insertC() {
  mapperC.insert()
}

public void test() {    
  serviceA.insertA()    // 没有事务
  serviceB.insertB()    // 开启事务A
}

在该示例中,调用者方法没有事务,serviceA.insertA()不开事务执行,serviceB.insertB()开启事务A执行,结果A添加成功,B被回滚。

示例四

// serviceA
@Transactional(propagation = Propagation.REQUIRED)
public void insertA() {
  mapperA.insert();
}

// serviceB
@Transactional(propagation = Propagation.REQUIRED)
public B insertB() {
  return mapperB.insert(B);
}
public void selectB(B) {
  mapperB.insert(B);
}


// serviceC
@Transactional(propagation = Propagation.REQUIRED)
public void insertC() {
  mapperC.insert(C);
}

@Transactional(propagation = Propagation.REQUIRED)
public void test1() {    // 开启事务A
  serviceA.insertA()    // 加入事务A
  B b serviceB.insertB()    // 加入事务A
  serviceB.selectB(b)   // 查询到serviceB.insertB()添加的数据,因为查询和添加在一个事务中
}


public void test2() {    
  serviceA.insertA()    // 开启事务A
  B b = serviceB.insertB()    // 开启事务B
  serviceB.selectB(b)   // 查询不到serviceB.insertB()添加的数据,因为serviceB.insertB()添加操作和查询并不在一个事务中。
}
posted @ 2022-03-15 00:11  我爱这世间美貌女子  阅读(635)  评论(0编辑  收藏  举报