Spring事务传播行为

Posted 荠菜煎包

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring事务传播行为相关的知识,希望对你有一定的参考价值。

Spring事务传播行为有7种:

spring的7种传播行为:
1.required:(默认传播行为),如果当前有事务,其他就用当前事务,不会新增事务。
例如:方法A调用方法B,它们用同一个事务。(如果B没有事务,它们会用同一个事务。)(只要有一个回滚,整体就会回滚)

2.requires_new:如果当前有事务,其他不会加入当前事务,会新增事务。即他们的事务没有关系,不是同一个事务。
如果其他没有事务,那么以当前事务运行。
例如:方法A调用方法B,它们用不同的事务。(B不会用A的事务,会新增事务。)

3.supports:当前没有事务,就以非事务运行。当前有事务呢?就以当前事务运行。
例如:方法A调用方法B,如果A没有事务,那么B就以非事务运行。
如果A有事务就以A事务为准。如果A没有事务,那么B就会以非事务执行。

4.mandatory:其他没有事务就会抛异常。当前没有事务抛出异常,当前有事务则支持当前事务。
支持当前事务,如果当前没有事务就会抛出异常。
例如:方法A调用方法B,如果方法A没有事务,那么就会抛出异常。

5.not_supported:以非事务执行。
例如:方法A调用方法B,方法B会挂起事务A以非事务方式执行。

6.never:以非事务执行,如果存在事务,抛出异常。
总是以非事务执行,如果存在事务,那么就抛出异常。

7.nested:如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。
如果当前事务不存在,那么其行为与Required一样。
例如:方法A中调用了方法B,B中try catch手动回滚,A不会回滚。

======================================

1.required:(默认传播行为),如果当前有事务,其他就用当前事务,不会新增事务。
例如:方法A调用方法B,它们用同一个事务。(如果B没有事务,它们会用同一个事务。)(只要有一个回滚,整体就会回滚)

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
    
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addTest()
        testDao.addTest();
        int i = 1/0;
    
REQUIRED表示在同一个事务:
1.addTest异常会使得整个事务回滚,user表和test表都没插入成功。
2.addUser异常也会使得事务回滚,user表和test表都没插入成功。

2.requires_new:如果当前有事务,其他不会加入当前事务,会新增事务。即他们的事务没有关系,不是同一个事务。
如果其他没有事务,那么以当前事务运行。
例如:方法A调用方法B,它们用不同的事务。(B不会用A的事务,会新增事务。)

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
    

@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void addTest()
        try 
            testDao.addTest();
            int i = 1/0;
         catch (Exception e)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        
    

REQUIRES_NEW表示addTest新创建了一个事务,跟addUser不在同一个事务里。两个事务互不影响。
1.addTest异常,进行回滚。addUser没有回滚。user表插入成功,test表插入失败。
2.addUser异常,进行回滚。addTest没有回滚。test表插入成功,user表插入失败。

3.supports:当前没有事务,就以非事务运行。当前有事务呢?就以当前事务运行。
例如:方法A调用方法B,如果A没有事务,那么B就以非事务运行。
如果A有事务就以A事务为准。如果A没有事务,那么B就会以非事务执行。

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
        int i = 1/0;
    

@Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    public void addTest()
        try 
            testDao.addTest();
         catch (Exception e)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        
    

如果addUser有事务,那么addTest跟addUser在同一个事务。如果addUser没有事务,那么就以非事务方式运行。

4.mandatory:其他没有事务就会抛异常。当前没有事务抛出异常,当前有事务则支持当前事务。
支持当前事务,如果当前没有事务就会抛出异常。
例如:方法A调用方法B,如果方法A没有事务,那么就会抛出异常。

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
        int i = 1/0;
    

@Transactional(propagation = Propagation.MANDATORY,rollbackFor = Exception.class)
    public void addTest()
        try 
            testDao.addTest();
         catch (Exception e)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        
    

如果addUser有事务,那么addTest跟addUser在同一个事务。如果addUser没有事务,那么就会报异常:No existing transaction found for transaction marked with propagation 'mandatory'

5.not_supported:以非事务执行。
例如:方法A调用方法B,方法B会挂起事务A以非事务方式执行。

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
        int i = 1/0;
    

@Transactional(propagation = Propagation.NOT_SUPPORTED,rollbackFor = Exception.class)
    public void addTest()
        try 
            testDao.addTest();
         catch (Exception e)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        
    

如果addUser异常,会回滚。addTest不会滚。不管addUser是否有事务,addTest都以非事务方式运行。

6.never:以非事务执行,如果存在事务,抛出异常。
总是以非事务执行,如果存在事务,那么就抛出异常。

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
        int i = 1/0;
    

@Transactional(propagation = Propagation.NEVER,rollbackFor = Exception.class)
    public void addTest()
        try 
            testDao.addTest();
         catch (Exception e)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        
    

如果addUser没有事务,addTest以非事务方式运行。如果addUser有事务,addTest就会报错:Existing transaction found for transaction marked with propagation 'never'

never和mandatory正好相反。

7.nested:如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。
如果当前事务不存在,那么其行为与Required一样。
例如:方法A中调用了方法B,B中try catch手动回滚,A不会回滚。

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addUser()
        userDao.addUser();
        testService.addTest();
    

@Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
    public void addTest()
        try 
            testDao.addTest();
            int i = 1/0;
         catch (Exception e)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        
    

addUser的事务内嵌addTest的事务,如果addUser异常回滚,那么addTest也会回滚。如果addTest回滚,addUser不会回滚。

nested和requires_new的不同是:

nested内层事务回滚不影响外层,外层事务回滚影响内层跟着回滚。

requires_new外层和内层不是同一个事务,互不影响。外层回滚不影响内层,内层回滚不影响外层。

以上是关于Spring事务传播行为的主要内容,如果未能解决你的问题,请参考以下文章

Spring事务的传播行为

Spring框架学习笔记 --- [Spring的事务传播行为]

Spring事务传播行为

Spring事务传播行为详解

Spring中事务传播行为

Spring事务传播行为