Spring事务的7种传播机制实例代码及分析

spring定义了7种事务传播机制

REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED)

SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS)

MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY)

REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW)

NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)

NEVER(TransactionDefinition.PROPAGATION_NEVER)

NESTED(TransactionDefinition.PROPAGATION_NESTED)

 
下面会根据上面其中传播行为进行实际代码测试:

 
测试前准备 :
 

实体类

@Data
public class TransactionalUser {
    
    
    private String userName;


    private String userNo;


    private Integer id;


    private Integer age;


    public TransactionalUser() {
    
    
    }


    public TransactionalUser(String userName, String userNo, Integer age) {
    
    
        this.userName = userName;
        this.userNo = userNo;
        this.age = age;
    }
}

Mapper

insert into transactional_test(user_name,user_no,age) values (#{userName},#{userNo},#{age})

测试类

注 : 这里为什么测试的每个方法都要分成不同类;主要是因为同类调用会致使事务失效;

@Service
public class TransactionalTest {
     
     

    @Autowired
    private A methodA;

    @Autowired
    private B methodB;

    @Autowired
    private PurchaseMapper purchaseMapper;

    public void send() {
     
     
        methodA.testA();
    }

    @Service
    class A {
     
     
        public void testA() {
     
     
            TransactionalUser user = new TransactionalUser("A","123",1);
            // A方法添加数据
            purchaseMapper.transactionalInsert(user);
            methodB.testB();
        }

    }

    @Service
    class B {
     
     
        @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testB() {
     
     
            TransactionalUser user = new TransactionalUser("B","321",2);
            // B方法添加数据
            purchaseMapper.transactionalInsert(user);
        }
    }

}

1、Propagation.REQUIRED : @Transactional 注解默认属性;如果当前存在事务就加入该事务,如果当前没有事务就新建一个事务。

示例1: A方法不加事务,B方法加入事务;

@Service
class A {
     
     
    public void testA() {
     
     
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
       // int i = 5/0;
    }
}


@Service
class B {
     
     
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testB() {
     
     
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法加入异常,A、B事务都不回滚。
B方法加入异常,A事务不回滚,B事务回滚。

示例2 : A方法加事务B方法不加事务

@Service
class A {
      
      
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
      
      
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }
}


@Service
class B {
      
      
    public void testB() {
      
      
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法加入异常,A、B事务都回滚
B方法加入异常,A、B事务都回滚。

示例3 : A方法加事务B方法加事务

@Service
class A {
       
       
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
       
       
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }


}

@Service
class B {
       
       
      // B的事务会加入到A中
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testB() {
       
       
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法加入异常,A、B事务都回滚
B方法加入异常,A、B事务都回滚
 

===================================== 分隔线 =====================================
 
2、Propagation.SUPPORTS : 支持当前事务,如果当前没有事务,就以非事务方式运行

示例1 : A方法没有事务,B方法加入事务

@Service
class A {
        
        
   // @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
        
        
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5/0;
    }

}


@Service
class B {
        
        
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void testB() {
        
        
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法加入异常,A、B事务都不回滚
B方法加入异常,A、B事务都不回滚
 

示例2 : A方法加入事务,B方法加入事务

@Service
class A {
         
         
       @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
         
         
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }


}

@Service
class B {
         
         
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void testB() {
         
         
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法加入异常,A、B事务都回滚
B方法加入异常,A、B事务都回滚
 

===================================== 分隔线 =====================================
 

3、Propagation.MANDATORY : 支持当前事务,如果不存在事务,则抛出异常

示例1: A方法不加事务,B方法加入事务

@Service
class A {
          
          
       //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
        public void testA() {
          
          
        TransactionalUser user = new TransactionalUser("A","123",1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }
}


@Service
class B {
          
          
    @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
    public void testB() {
          
          
        TransactionalUser user = new TransactionalUser("B","321",2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常不会回滚,B方法不执行,并抛出 " No existing transaction found for transaction marked with propagation ‘mandatory’" 异常

示例2 : A方法加事务,B方法加事务

@Service
class A {
           
           
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
           
           
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }

}

@Service
class B {
           
           
    @Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
    public void testB() {
           
           
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A、B事务都回滚
B方法异常,A、B事务都回滚
 

===================================== 分隔线 =====================================
 

4、Propagation.REQUIRES_NEW : 如果有事务存在,挂起当前事务,并创建一个新的事务

示例1: A方法不加事务,B方法加入事务

@Service
class A {
            
            
    //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
            
            
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }
}

@Service
class B {
            
            
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void testB() {
            
            
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A、B事务都不回滚
B方法异常,A事务不回滚、B事务回滚
 

示例2 : A方法加入事务,B方法加入事务

@Service
class A {
             
             
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
             
             
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }


}

@Service
class B {
             
             
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void testB() {
             
             
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A事务回滚,B事务不回滚
B方法异常,A、B事务都回滚
 
这里总结一下,REQUIRES_NEW的这种情况,外层事物的异常不会影响内层事务,但内层事务的异常是会影响到外层事务。

===================================== 分隔线 =====================================
 

5、Propagation.NOT_SUPPORTED : 以非事务方式运行,如果有事务存在,挂起当前事务。

示例1 : A方法无事务,B方法加入事务

@Service
class A {
               
               
    //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
               
               
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
        int i = 5 / 0;
    }

}

@Service
class B {
               
               
    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public void testB() {
               
               
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A方法异常,A、B事务都不回滚
B方法异常,A、B事务都不回滚
 

示例2 : A方法加入事务,B方法加入事务

@Service
class A {
                
                
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
                
                
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }

}

@Service
class B {
                
                
    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public void testB() {
                
                
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
        int i = 5/0;
    }
}

结果 :

A方法异常,A事务回滚、B事务不回滚
B方法异常,A事务回滚、B事务不回滚
 

总结一下,这里A方法异常时,看似和"REQUIRES_NEW"很像,都是挂起了A事务,这样A和B两个方法就完全互不影响了,区别在于B方法,一个有事务,一个没事务。

===================================== 分隔线 =====================================
 

6、Propagation.NEVER : 以非事务方式运行,如果有事务则抛出异常

示例1: A方法开启事务,B方法开启事务

@Service
class A {
                  
                  
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void testA() {
                  
                  
        TransactionalUser user = new TransactionalUser("A", "123", 1);
        // A方法添加数据
        purchaseMapper.transactionalInsert(user);
        methodB.testB();
    }
}

@Service
class B {
                  
                  
    @Transactional(propagation = Propagation.NEVER, rollbackFor = Exception.class)
    public void testB() {
                  
                  
        TransactionalUser user = new TransactionalUser("B", "321", 2);
        // B方法添加数据
        purchaseMapper.transactionalInsert(user);
    }
}

结果 :

A、B数据都没成功添加,并抛出异常 "Existing transaction found for transaction marked with propagation 'never'"

===================================== 分隔线=====================================
 
7、Propagation.NESTED : 如果当前存在事务,则以嵌套方式执行

在做这种方式的传播行为的测试时,思考了很久,因为不太清楚"嵌套"到底是什么概念,以及和其它传播行为的区别是什么?搜索了资料 参考了 这篇博客

https://www.jianshu.com/p/c6d4095f5833

总结一下Propagation.NESTED,就是上面那篇博客中最后提到的

  • 主事务和嵌套事务属于同一个事务

  • 嵌套事务出错回滚不会影响到主事务

  • 主事务回滚会将嵌套事务一起回滚了

猜你喜欢

转载自blog.csdn.net/smlie_shuihan/article/details/117596499