spring嵌套事务,try-catch事务处理

2 篇文章 0 订阅

spring 事务总结

前置条件

表Teacher 别名 A ,表Student 别名 B 分别插入。

A中启动事务,B中不启动事务 testDemo01调用方法开启事务

testDemo01开启事务,A中insert中开启事务,调用执行,A中执行成功,B中执行出现异常,AB事务回滚。
//A 表处理   
		@Override
    @Transactional
    public int insert(Teacher record) {

        log.info("teacher 插入开始....");
        return teacherDAO.insert(record);
    }
//B表处理
 		@Override
    public int insert(Student record) {
        log.info("Student 插入处理....");
        return studentDAO.insert(record);
    }
//调用方法处理
    @Transactional
    public void testDemo01() throws Exception{

        teacherService.insert(getTeacherEntity(2));
        studentService.insert(getStudentEntity(2));
    }

A,B调用顺序调整。testDemo01开启事务,A中insert中开启事务,调用执行,A中执行异常,B中执行成功,AB事务回滚。
 @Transactional
    public void testDemo01() throws Exception{

        studentService.insert(getStudentEntity(2));
        teacherService.insert(getTeacherEntity(2));

    }
//A
@Override
    @Transactional
    public int insert(Teacher record) {

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }
A中事务开启新事务,调用后A调用异常,B中正常,A事务回滚,B事务不回滚
//A
@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }
A中开启事务,并使用try catch 将异常抓取。结果 A插入成功,B插入成功。事务没有执行会滚。
//调用方法
@Transactional
    public void testDemo01() throws Exception{

        studentService.insert(getStudentEntity(2));
        teacherService.insert(getTeacherEntity(2));

    }
//A
		@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try{
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        }catch (Exception e){
            log.error(e.getMessage());
        }

        return ss;
    }
调用方法使用try catch 抓取异常。A方法正常抛出异常,事务进行了会滚,也就是student和teacher都进行了会滚。但是报 Transaction rolled back because it has been marked as rollback-only 异常,这个异常简单来讲,就是事务的传播机制导致的,teacher事务默认是用testDemo01调用方法的事务,但是teacher异常抛出的时候,teacher事务被标记成rollback 状态,所以,在调用方法testDemo01中即使使用trycatch捕捉了异常,同样也会做会滚,以为他俩使用的一个事务。
//调用方法
@Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(3));
            teacherService.insert(getTeacherEntity(3));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//Teacher方法
@Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }
调整teacher的事物传播机制为 (propagation = Propagation.REQUIRES_NEW),然后teacher会回滚,Student不会进行回滚。
 @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(3));
            teacherService.insert(getTeacherEntity(3));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//
 @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }
testDemo01方法和Teacher 都使用trycatch 处理,Teacher不抛出异常,testDemo01也不抛出异常,AB不回滚
 @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(4));
            teacherService.insert(getTeacherEntity(3));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//
 @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return ss;
    }

testDemo01方法和Teacher 都使用trycatch 处理,Teacher修改事物隔离级别,不抛出异常,testDemo01也不抛出异常,AB不回滚
@Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(5));
            teacherService.insert(getTeacherEntity(4));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//
@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return ss;
    }
testDemo01方法和Teacher 都使用trycatch 处理,Teacher抛出异常,testDemo01不抛出异常,AB不回滚
  @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(6));
            teacherService.insert(getTeacherEntity(5));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
// @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new Exception(e.getMessage());
        }

        return ss;
    }
testDemo01方法和Teacher 都使用trycatch 处理,Teacher抛出异常,testDemo01抛出异常(不指定那个异常回滚,注意异常要是RuntimeException,不能是其以上的异常,不然会会滚失败,或者指定异常会滚),AB回滚
  @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(8));
            teacherService.insert(getTeacherEntity(7));
        }catch (Exception e){
            log.error(e.getMessage());
            throw new RuntimeException(e.getCause());
        }

    }
//或者指定会滚异常
 @Transactional(rollbackFor = {Exception.class})
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(8));
            teacherService.insert(getTeacherEntity(7));
        }catch (Exception e){
            log.error(e.getMessage());
            throw new Exception(e.getCause());
        }

    }
//
 @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new Exception(e.getMessage());
        }

        return ss;
    }
如果使用循环的方式处理异常,如何保证每次循环中 testDemo01中student和teacher 同时会滚,同时有不影响下次插入呢,就是,student每新增一条数据,teacher新增三条,他们的事务在一个事务中,每次执行一次遍历 ,AB都新增数据。然而在遍历中,某一次遍历出现异常后,AB都进行会滚,同时不影响上次遍历数据,不能中断遍历。解决办法是在调用方法时,首先要设立事务的传播特性修改成REQUIRES_NEW(开启新的事务,不在归调用者的事务管理,每次遍历的时候都会开启新事务),另外使用trycatch捕获异常后使用手动操作异常时会滚(这样就不会影响下次遍历了)。异常是否抛出对于调用者不影响。
@Transactional
    public void testC() throws Exception{

        for (int i = 1; i <4; i++) {
            try {
                testService.testDemo01(i);
            } catch (Exception e) {
                continue;
            }
        }
    }
//
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = {Exception.class})
    public void testDemo01(int i) throws Exception{

        try{
            studentService.insert(getStudentEntity(i));
            teacherService.insert(getTeacherEntity(i));
        }catch (Exception e){
            log.error(e.getMessage());
     		//手动回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new Exception(e.getCause());
        }

    }
//
  @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            int k= record.getId();
            for (int i = 1; i < 3; i++) {

                if (k==1){
                    record.setId(1+i);
                }
                if (k==2){
                    record.setId(3+i);
                }
                if (k==3){
                    record.setId(6+i);
                }
                ss = teacherDAO.insert(record);

                if (k==2){
                    int t = 1 / 0;
                }
            }

        } catch (Exception e) {
            log.error(e.getMessage());
            throw new Exception(e.getMessage());
        }

        return ss;
    }
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值