您当前的位置: 首页 >  spring

梁云亮

暂无认证

  • 1浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring事务的传播行为

梁云亮 发布时间:2020-06-17 14:10:21 ,浏览量:1

相关代码: Spring事务传播特性代码 GitHub

REQUIRED

如果当前没有开启事务,就开启一个新事务,如果当前开启了事务,就加入该事务。

  • Service层代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int deleteByDeptno(Integer deptno) {
        deptMapper.deleteByPrimaryKey(deptno);
        throw new RuntimeException("数据删除出错"); //模拟出错
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    //@Transactional(propagation = Propagation.REQUIRED)
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByDeptno(84);//更新
        System.out.println(3 / 0); //模拟出错
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImplTest {
    @Resource(name = "deptService")
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }
}

如果save()方法没有开启事务,insert()方法不会回滚,delete()方法开启了事务,delete会回滚。 如果save()方法开启了事务,则delete()方法不会开启新事务,会加入到save()方法的事务中,insert()方法和delete()方法都会回滚。

SUPPORTS

如果当前开启了事务,就加入该事务,否则非事务执行。

  • Service代码:
@Service("deptService5")
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public int deleteByDeptno(Integer deptno) {
        deptMapper.deleteByPrimaryKey(deptno);
        throw new RuntimeException("数据删除出错"); //模拟出错
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    public int save(Dept record) { //没有开启事务
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByDeptno(84);//更新
        System.out.println(3 / 0); //模拟出错
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImplTest {
    @Resource(name = "deptService")
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }
}

如果save()方法没有开启事务,delete()方法也不会开启事务,insert()方法和delete()方法操作均不会回滚。 如果save()方法开启了事务,delete()方法会加入到save()方法的事务中,则insert()方法和delete()方法均会回滚。

MANDATORY

如果当前开启了事务,就加入该事务,否则抛出异常。说白了,强制事务,不允许非事务执行。

  • Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.MANDATORY)
    public int deleteByDeptno(Integer deptno) {
        deptMapper.deleteByPrimaryKey(deptno);
        throw new RuntimeException("数据删除出错"); //模拟出错
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByDeptno(87);//更新
        System.out.println(3 / 0); //模拟出错
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImplTest {
    @Resource(name = "deptService")
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }
}

如果save()方法没有开启事务,执行delete()方法时会抛出异常:insert()方法成功,delete()方法操作没有执行。 如果save()方法开启了事务,则delete()方法加入到事务中,不会抛异常。

REQUIRES_NEW

如果当前没有开启事务,则开启一个新事务来执行。 如果当前开启了事务,则将当前事务挂起,开启一个新事务来执行。 外层事务和内层事务是互相隔离的,内层事务的提交或回滚不影响外层事务,外层事务的提交或回滚也不影响内层事务。 需要捕获内层方法异常,否则内层方法抛异常,会影响外层事务回滚。

  • Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int deleteByDeptno(Integer deptno) {
        return deptMapper.deleteByPrimaryKey(deptno);
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    @Transactional
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByDeptno(87);//更新
        System.out.println(3 / 0); //模拟出错
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImpl9Test {
    @Resource(name = "deptService")
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }
}

save()方法开启了事务A,执行delete()时,会将save()方法的事务A挂起,并开启新事务B,delete()方法执行成功,事务B提交,然后恢复事务A,接着抛出异常,事务A回滚,但是事务B已经提交不会受到影响。最终delete()方法操作成功,insert()方法操作被回滚。

NOT_SUPPORTED

强制以非事务方式执行,如果当前开启了事务就将当前事务挂起再执行。

  • Service代码:
@Service("deptService")
public class DeptServiceImpl10 implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public int deleteByDeptno(Integer deptno) {
        int res = deptMapper.deleteByPrimaryKey(deptno);
        System.out.println(2/0);
        return res;
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    @Transactional
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByDeptno(88);//更新
        System.out.println(3 / 0); //模拟出错
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImpl10Test {
    @Resource(name = "deptService")
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }
}

save()方法开启了事务,执行delete()方法时会挂起事务,然后以非事务的方式执行delete()方法并提交,然后恢复事务,由于save()方法抛出异常,insert回滚。 结果insert()方法回滚、delete()方法正常提交。

NEVER:非事务执行,如果当前开启了事务则抛出异常。
  • Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public int deleteByDeptno(Integer deptno) {
        int res = deptMapper.deleteByPrimaryKey(deptno);
        System.out.println(2/0);
        return res;
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    @Transactional
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByDeptno(88);//更新
        System.out.println(3 / 0); //模拟出错
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImpl11Test {
    @Resource(name = "deptService")
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }
}
  • 如果save()方法开启了事务,导致delete()方法抛出异常: 在这里插入图片描述
  • 如果save()方法没有开启事务,则save()方法和delete()方法都会以非事务执行。
NESTED

如果方法没有开启事务,则开启一个新事务来执行,否则,在当前事务中以嵌套事务的方式执行。嵌套事务执行前,会创建一个保存点savePoint,如果方法异常,则回滚到该savePoint,否则等待和外层事务一起Commit。

  • Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public int deleteByDeptno(Integer deptno) {
        int res = deptMapper.deleteByPrimaryKey(deptno);
        System.out.println(2 / 0);
        return res;
    }
    
    @Resource(name = "deptService")
    private DeptService deptService;
    @Override
    @Transactional
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = 0;//更新
        try {//delete执行前,保存一个savePoint,如果delete异常,则回滚到savePoint,否则等待和save一起提交事务
            res2 = deptService.deleteByDeptno(88);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //System.out.println(3 / 0); //模拟出错,如果出错insert和delete会一起回滚
        return res1 + res2;
    }
}
  • 测试代码:
@SpringBootTest
class DeptServiceImpl12Test {

    @Resource(name = "deptService12")
    private DeptService deptService;

    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.save(dept);
        System.out.println(insert);
    }

}

如果3/0行代码不注释,则出错,insert和delete方法都回滚;否则都正常提交。

关注
打赏
1665409997
查看更多评论
立即登录/注册

微信扫码登录

0.0507s