Spring事务管理中常用的传播行为有以下几种:
1. PROPAGATION_REQUIRED(默认值)
如果当前没有事务,则创建一个新的事务;如果当前存在事务,则加入到当前事务中。该传播行为是最常用的。在大部分情况下,我们都需要对于数据敏感度高(比如钱)的操作使用该传播行为,来确保操作的原子性和数据的一致性。
使用场景:当一个方法被执行时,如果当前上下文中已经存在一个事务,那么该方法则会在这个事务中执行;如果当前不存在事务,则会新建一个事务,包含整个方法执行过程;如果该方法中调用了其他带有事务注解的方法,则子方法会加入到当前事务中。
2. PROPAGATION_SUPPORTS
如果当前存在事务,则加入到当前事务中;如果当前没有事务,则以非事务方式执行操作。该传播行为用于执行一些不需要事务保证的操作,这样可以减少事务操作,从而减小整体事务的开销。
使用场景:当一个方法被执行时,如果当前上下文中已经存在一个事务,则在事务中执行;如果当前没有事务,则不启动事务,以普通的非事务方式运行;在子方法被执行时,父方法无论使用什么事务传播行为,都不能为子方法开启事务的占用。
3. PROPAGATION_MANDATORY
如果当前存在事务,则加入到当前事务中;如果当前不存在事务,则抛出异常。该传播行为用于强制事务执行,如果当前没有事务,则抛出异常,由调用者来处理。
使用场景:当一个方法被执行时,如果当前上下文中已经存在一个事务,则在该事务中执行;如果当前没有正在执行的事务,就抛出异常,让调用者来处理。
4. PROPAGATION_REQUIRES_NEW
无论当前是否有事务存在,都会开启一个新的事务。通常使用在需要将当前事务回滚时,而子事务不想被回滚的情况下。
使用场景:无论当前上下文中是否存在事务,该方法都会启用独立的事务,即调用者的事务会被挂起,新的事务并不依赖于调用者的事务。新启用的事务拥有自己独立的数据库连接和锁资源,受事务自己的控制。即使独立事务步骤报错,不会使调用者事务回滚到该方法执行前的状态,但独立事务仍保证了其语句执行的原子性。
5. PROPAGATION_NOT_SUPPORTED
如果当前存在事务,则将事务挂起,以非事务方式执行操作;如果当前不存在事务,则以非事务方式执行操作。该传播行为用于不需要事务保证的操作,可以减少事务操作,从而减小整体事务的开销。
使用场景:无论当前上下文中存不存在事务,都在非事务环境下执行。如果在子方法中执行,调用方方法的事务没有受到影响。另外,如果未加事务注解,但是需要整个操作保持一个临时的全局状态,比如协议状态,也可以用该传播行为。
6. PROPAGATION_NEVER
如果当前存在事务,则抛出异常;如果当前不存在事务,则以非事务方式执行操作。该传播行为用于禁止事务执行,如果当前已经存在事务,则抛出异常。
使用场景:如果一个方法已经在事务中,则该方法的方法体中的内容会被按照预期的方式执行;如果方法体中的内容是作为实现的一部分来执行的,就需要确保在调用该方法时不能开启新的事务。该传播行为的效果就是,如果事务已经在运行中,则禁止开启新的事务并报错;否则则可以正常执行。
7. PROPAGATION_NESTED
如果当前存在事务,则新开嵌套事务并执行;如果当前不存在事务,则新建事务并执行。该传播行为用于对于部分事务能够成功,但还需要其他部分执行后才能提交的场景。
使用场景:使用该传播行为时,如果父方法存在声明式事务,那么该方法使用子事务,即独立于父事务的子事务,作为整个父事务的子事务。其关系类似于子事务和父事务之间的“内外依赖”,按照该传播行为的规则,子事务就会受父事务的控制。同时,当子事务回滚时,实质上是在子事务内部回滚而不会对父事务产生影响,如果父事务存在声明式事务,那么它也不会因为子事务的回滚而回滚。
以上是常用的事务传播行为及其使用场景。按照具体的场景来选择不同的传播行为,可以有效地保证事务的执行效率和正确性。