springboot事务传播

374 阅读3分钟

springboot的事务处理是由PlatformTransactionManager的具体实现类来完成的,如事务管理器PlatformTransactionManager用来管理JDBC的事务.JpaTransactionManager用来管理JPA的事物

在使用springboot的事务之前我们需要知道一个机制.

In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.

意思就是:在默认的代理模式下,只有目标方法由外部调用,才能被事务拦截器拦截到.如果是在同一个类中的两个方法直接调用是不会被事务拦截器拦截到的.我们看下面的例子

@Service
class TestService{

    @Autowired
    private lateinit var accountRepository: AccountRepository

    @Autowired
    private lateinit var txService: TxService

    @Transactional
    fun save(){

        调用同一类中的方法
        trail()
        val account = Account(name = "柯基")
        accountRepository.save(account)
        
        
        //制造异常
        1/0

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    fun trail(){

        val account = Account(name = "哈士奇")
        accountRepository.save(account)

    }
}

结果是数据都木有 插入数据库.这是因为trail()并未被事务拦截器拦截到.它还是和save()方法处于同一个事务中.

如果我们将save()的@Transactional注解去掉,结果是两条数据都插入到了数据库.因为整个调用过程是不会创建事务的.

下面我们来看一看事务的传播行为

我们通过@Transactional 注解的propagation属性来指定.默认是Propagation.REQUIRED

  • Propagation.REQUIRED

如果当前存在事务,则加入该事务.若当前不存在事务,则创建一个新的事务

  • Propagation.SUPPORTS

如果当前存现事务,则加入该事务,若不存在则以非事务的方式运行

  • Propagation.REQUIRES_NEW

重新创建一个事务,如果当前事务存在,则暂停当前事务,等到新创建的事务提交后恢复事务.

  • Propagation.NOT_SUPPORTED

以非事务的方式运行,若当前存在事务,则暂停当前事务

  • Propagation.NEVER

以非事务的方式运行,若当前存在事务,则抛出异常.

  • Propagation.NESTED

和 Propagation.REQUIRED 效果一样

  • Propagation.REQUIRED示例

@Service
class TestService{

    @Autowired
    private lateinit var accountRepository: AccountRepository

    @Autowired
    private lateinit var txService: TxService

    @Transactional
    fun save(){

        
        txService.trail()
        
        
        val account = Account(name = "柯基")
        accountRepository.save(account)
        
        
        //制造异常
        1/0

    }
}

@Service
class TxService{

    @Autowired
    private lateinit var accountRepository: AccountRepository


    @Transactional(propagation = Propagation.REQUIRED)
    fun trail(){

        val account = Account(name = "哈士奇")
        accountRepository.save(account)

    }
}

结果是不会插入数据到数据库.两个方法处于同一事务中,且事务被中断

  • Propagation.REQUIRES_NEW

@Service
class TestService{

    @Autowired
    private lateinit var accountRepository: AccountRepository

    @Autowired
    private lateinit var txService: TxService

    @Transactional
    fun save(){

       
        txService.trail()
        
        
        val account = Account(name = "柯基")
        accountRepository.save(account)
        
        
        //制造异常
        1/0

    }
}

@Service
class TxService{

    @Autowired
    private lateinit var accountRepository: AccountRepository


    @Transactional(propagation = Propagation.REQUIRES_NEW)
    fun trail(){

        val account = Account(name = "哈士奇")
        accountRepository.save(account)

    }
}

结果是只有哈士奇被插入到数据库中,txService.trail()是创建了新的事务不受一异常的影响

  • Propagation.SUPPORTS

@Service
class TestService{

    @Autowired
    private lateinit var accountRepository: AccountRepository

    @Autowired
    private lateinit var txService: TxService

    //@Transactional
    fun save(){

       
        txService.trail()
        
        
        val account = Account(name = "柯基")
        accountRepository.save(account)
        
        
       

    }
}

@Service
class TxService{

    @Autowired
    private lateinit var accountRepository: AccountRepository


    @Transactional(propagation = Propagation.SUPPORTS)
    fun trail(){

        val account = Account(name = "哈士奇")
        accountRepository.save(account)
        //制造异常
        1/0
    }
}

trail()以非事务的方式执行,所以哈士奇会被插入到数据库