目录
Spring 框架中的事务传播行为定义了在多个事务操作嵌套执行时,如何处理事务的传播和管理。Spring 提供了多种事务传播行为,以满足不同的业务需求。以下是 Spring 中常见的七种事务传播行为的介绍。
一、REQUIRED
REQUIRED 是 Spring 框架中的默认事务传播行为。当一个方法被声明为 REQUIRED 时,它会检查当前是否存在一个事务。如果存在事务,则该方法将加入到该事务中执行;如果不存在事务,则会创建一个新的事务。以下是对 REQUIRED 传播行为的详细介绍:
1.1 默认传播行为
REQUIRED 是 Spring 中事务传播行为的默认选项。如果不明确指定传播行为,则默认为 REQUIRED。
这意味着大多数情况下,一个方法会在一个已存在的事务中执行,或者如果没有事务存在,则会为该方法创建一个新的事务。
1.2 事务的加入与创建
当调用一个使用 REQUIRED 传播行为的方法时,该方法会尝试加入当前已经存在的事务中执行。
如果当前不存在事务,则该方法会创建一个新的事务,然后在新的事务中执行。
1.3 适用场景
REQUIRED 适用于绝大多数的事务场景,特别是当一个方法的执行需要在事务中进行,但不要求该方法独立创建事务时。
如果一个方法需要依赖于外部事务的一致性,或者需要确保数据的完整性,那么可以将该方法的事务传播行为设置为 REQUIRED。
1.4 示例应用
在一个服务类中,如果有一个方法需要在事务中执行,可以将该方法的事务传播行为设置为 REQUIRED。这样,当其他方法调用这个需要在事务中执行的方法时,它们会共享同一个事务。
例如,一个银行转账的操作,需要保证从一个账户扣款和向另一个账户转账的操作在同一个事务中执行,以保证数据的一致性,这时可以将这两个操作的方法的事务传播行为设置为 REQUIRED。
1.5 与其他传播行为的区别
REQUIRED 与 REQUIRES_NEW 的区别在于,REQUIRED 不会开启一个新的事务,而是依赖于外部事务的存在,如果外部没有事务则创建一个新事务;而 REQUIRES_NEW 则会始终开启一个新的事务。
与 SUPPORTS 传播行为相比,REQUIRED 会主动创建事务,而不是依赖于当前是否存在事务。
总结:REQUIRED 是 Spring 中最常用的事务传播行为之一,适用于大多数需要在事务中执行的业务方法。它确保了方法的执行在事务中,从而保证了数据的一致性和完整性。
二、SUPPORTS
SUPPORTS 是 Spring 框架中的一种事务传播行为。它的主要特点是,如果当前存在事务,则该方法会加入到该事务中执行;如果当前不存在事务,则该方法以非事务方式执行。以下是对 SUPPORTS 传播行为的详细介绍:
2.1 以非事务方式执行
当一个方法被声明为 SUPPORTS 传播行为时,它会在当前存在事务的情况下加入到该事务中执行,如果当前不存在事务,则会以非事务方式执行。
这意味着该方法可以被事务包围,也可以独立于事务之外执行。
2.2 适用场景
SUPPORTS 适用于不需要强制在事务中执行的场景,但仍然可以利用已存在的事务来保证数据的一致性。
当一个方法并不强制需要在事务中执行,但是可以与已存在的事务一起执行,这时可以将该方法的事务传播行为设置为 SUPPORTS。
2.3 示例应用
在一个服务类中,有一些查询方法可能不需要在事务中执行,但是可以利用已存在的事务,例如读取一些不需要事务保护的配置信息或者只读数据。这时可以将这些方法的事务传播行为设置为 SUPPORTS。
例如,在一个订单管理系统中,有一个方法用于查询订单的详细信息,这个方法并不会修改订单数据,只是简单地读取订单信息。在这种情况下,可以将该方法的事务传播行为设置为 SUPPORTS,以避免不必要的事务开销。
2.4 与其他传播行为的区别
SUPPORTS 与 REQUIRED 的区别在于,SUPPORTS 不会主动创建事务,而是依赖于当前是否存在事务。如果存在事务,则加入到该事务中执行;如果不存在事务,则以非事务方式执行。而 REQUIRED 则会主动创建事务。
与 NOT_SUPPORTED 传播行为相比,SUPPORTS 会与当前已存在的事务进行关联,而 NOT_SUPPORTED 则会强制以非事务方式执行,即使当前存在事务也会挂起该事务。
总结:SUPPORTS 是一种用于不强制在事务中执行的场景的事务传播行为。它允许方法以非事务方式执行,同时可以利用已存在的事务来保证数据的一致性。
三、MANDATORY
MANDATORY 是 Spring 框架中的一种事务传播行为,其主要特点是必须在一个已存在的事务中执行,否则会抛出异常。这意味着如果在调用的方法中不存在事务,则会抛出异常,要求调用者在一个事务中执行。以下是对 MANDATORY 传播行为的详细介绍:
3.1 必须在事务中执行
当使用 MANDATORY 传播行为时,方法调用者必须在一个已存在的事务中执行,否则会抛出异常。
如果调用方法的代码没有事务上下文,则会抛出事务不可用的异常。这确保了方法的执行在一个事务中,增强了数据的一致性和完整性。
3.2 适用场景
MANDATORY 适用于需要确保某些方法在事务中执行的场景,而不允许它们被非事务方式调用。
例如,当某个方法的执行需要访问数据库或者进行其他事务性操作时,为了保证数据的一致性和完整性,可以将该方法的事务传播行为设置为 MANDATORY。
3.3 典型应用
在使用 Spring 事务管理时,可以通过将一些核心业务方法的事务传播行为设置为 MANDATORY,来保证这些方法在事务中执行。
例如,在一个服务类中,有一个方法需要确保在事务中执行,可以将该方法的事务传播行为设置为 MANDATORY。这样,当其他方法调用这个需要在事务中执行的方法时,如果它们没有在事务中执行,则会抛出异常。
3.4 与其他传播行为的区别
MANDATORY 与 REQUIRED 传播行为有些类似,但是它要求方法调用者在一个已存在的事务中执行,而不是创建一个新的事务。
与 REQUIRES_NEW 传播行为相比,MANDATORY 不会创建一个新的事务,而是依赖于外部事务的存在。
总结:MANDATORY 是一种用于强制方法调用者在已存在的事务中执行的事务传播行为。它确保了方法的执行在事务中,从而保证了数据的一致性和完整性。
四、REQUIRES_NEW
REQUIRES_NEW 是 Spring 框架中的一种事务传播行为,它的主要特点是始终会开启一个新的事务。无论当前是否存在事务,REQUIRES_NEW 都会挂起当前事务(如果存在的话),然后创建一个新的事务来执行方法。以下是对 REQUIRES_NEW 传播行为的详细介绍:
4.1 始终开启新事务
REQUIRES_NEW 总是会创建一个新的事务,无论当前是否存在事务。如果当前存在事务,则会将当前事务挂起;如果当前不存在事务,则直接创建一个新的事务。
这意味着 REQUIRES_NEW 方法的执行完全独立于外部事务,不受外部事务的影响,且不会与外部事务共享同一个事务上下文。
4.2 独立性和隔离性
由于 REQUIRES_NEW 方法开启的是一个全新的事务,因此它的执行是完全独立于外部事务的。这确保了方法的执行不会受到外部事务的影响,并且不会对外部事务产生任何影响。
REQUIRES_NEW 方法的事务与外部事务是隔离的,内部事务的提交或回滚不会影响外部事务的状态,反之亦然。
4.3 适用场景
REQUIRES_NEW 适用于需要确保方法执行在一个独立事务中的场景,且不受外部事务的影响。
当一个方法的执行需要完全独立于外部事务,并且可能需要单独的事务管理、提交或回滚时,可以将该方法的事务传播行为设置为 REQUIRES_NEW。
4.4 示例应用
在一个复杂的业务流程中,某些步骤需要在一个全新的事务中执行,以保证其独立性和隔离性。这时可以将这些步骤对应的方法的事务传播行为设置为 REQUIRES_NEW。
例如,在一个订单处理系统中,当需要对订单进行支付操作时,可以将支付操作的方法的事务传播行为设置为 REQUIRES_NEW,以确保支付操作在一个独立的事务中执行,不受订单创建或更新操作的影响。
总结:REQUIRES_NEW 是一种用于开启一个全新事务的事务传播行为。它确保了方法的执行在一个独立、隔离的事务中进行,适用于需要在方法执行过程中完全独立于外部事务的场景。
五、NOT_SUPPORTED
NOT_SUPPORTED 是 Spring 框架中的一种事务传播行为,它的主要特点是将方法的执行置为非事务方式。即使当前存在事务,该方法也会在不受事务管理的环境下执行。以下是对 NOT_SUPPORTED 传播行为的详细介绍:
5.1 以非事务方式执行
NOT_SUPPORTED 表示方法不应该在事务中执行,即使当前存在事务,该方法也会在非事务的环境下执行。
如果当前存在事务,则会将当前事务挂起,然后在非事务环境下执行方法;如果当前不存在事务,则直接以非事务方式执行方法。
5.2 独立于事务环境
NOT_SUPPORTED 方法的执行与事务环境完全独立。它不受外部事务的影响,也不会对外部事务产生任何影响。
这使得该方法可以在不需要事务保护的情况下执行,以提高执行效率或避免事务管理的开销。
5.3 适用场景
NOT_SUPPORTED 适用于不需要事务保护的操作,例如只读查询或者一些无需事务的操作。
当一个方法执行的操作与事务无关,或者不会对数据库的数据进行修改时,可以将该方法的事务传播行为设置为 NOT_SUPPORTED。
5.4 示例应用
在一个查询操作中,如果只是简单地读取数据而不对数据进行修改,那么可以将该查询方法的事务传播行为设置为 NOT_SUPPORTED。这样可以避免不必要的事务管理开销,提高查询效率。
例如,一个报表生成的方法,只是从数据库中读取数据并生成报表,不需要对数据库中的数据进行修改,可以将该方法的事务传播行为设置为 NOT_SUPPORTED。
5.5 注意事项
使用 NOT_SUPPORTED 传播行为需要注意可能存在的数据一致性问题。因为该方法的执行是在非事务环境下,如果需要保证数据的一致性,需要在业务逻辑上进行相应的处理。
总结:NOT_SUPPORTED 是一种用于将方法执行置为非事务方式的事务传播行为。它适用于不需要事务保护的操作,可以提高执行效率,减少不必要的事务管理开销。
六、NEVER
NEVER 是 Spring 框架中的一种事务传播行为,它的主要特点是绝对不允许方法在事务中执行。如果当前存在事务,则会抛出异常,阻止方法执行。以下是对 NEVER 传播行为的详细介绍:
6.1 绝对不支持事务
NEVER 表示方法绝对不应该在事务中执行。如果当前存在事务,则会抛出异常,阻止方法的执行。
这意味着该方法的执行必须在非事务环境下进行,无论外部是否存在事务,都不允许该方法执行在事务中。
6.2 独立于事务环境
NEVER 方法的执行与事务环境完全独立。它不受外部事务的影响,也不会对外部事务产生任何影响。
这使得该方法可以在完全不受事务管理的环境下执行,以确保操作的原子性和一致性。
6.3 适用场景
NEVER 适用于绝对不允许方法在事务中执行的场景。例如,一些特定的敏感操作或者需要绝对原子性的操作。
当一个方法的执行不能容忍在事务中进行,且需要确保原子性、一致性和隔离性时,可以将该方法的事务传播行为设置为 NEVER。
6.4 示例应用
在某些情况下,可能存在一些绝对不允许在事务中执行的操作,例如对某些系统关键配置的修改或者其他可能影响整个系统的操作。这时可以将这些操作对应的方法的事务传播行为设置为 NEVER,以确保其在非事务环境下执行,避免可能的数据不一致或并发问题。
总结:NEVER 是一种用于绝对不允许方法在事务中执行的事务传播行为。它确保了方法的执行在非事务环境下进行,可以用于确保敏感操作的原子性和一致性,或者避免可能的并发问题。
七、NESTED
NESTED 是 Spring 框架中的一种事务传播行为,它提供了一种嵌套事务的机制。嵌套事务是外部事务的一部分,但它可以独立于外部事务进行提交或回滚。嵌套事务在外部事务的范围内,但其提交或回滚不会影响外部事务的状态。以下是对 NESTED 传播行为的详细介绍:
7.1 嵌套事务的特点
NESTED 会在当前事务的内部开启一个新的嵌套事务,嵌套事务是外部事务的一部分。
嵌套事务可以独立于外部事务进行提交或回滚,但其提交或回滚不会影响外部事务的状态。
嵌套事务内部可以有自己的 savepoint,并且可以在内部事务中使用 rollbackToSavepoint() 方法回滚到指定的 savepoint。
7.2 适用场景
NESTED 适用于需要在一个事务中包含另一个独立事务的场景,且内部事务的提交或回滚不应该影响外部事务的场景。
当一个方法需要在事务中执行,但又需要将一部分操作作为一个独立的事务进行管理时,可以将该方法的事务传播行为设置为 NESTED。
7.3 示例应用
在某些业务场景中,可能存在一些需要在一个事务中包含另一个独立事务的操作,例如在订单处理中,创建订单和创建订单日志可能需要在同一个事务中执行,但是订单日志的创建可以独立于订单的创建进行提交或回滚。
这时可以将订单日志创建的方法的事务传播行为设置为 NESTED,以确保其在外部事务的范围内执行,且可以独立于外部事务进行提交或回滚。
7.4 与其他传播行为的区别
NESTED 和 REQUIRED 的区别在于,NESTED 是外部事务的一部分,而 REQUIRED 是外部事务的一部分,但它们的提交或回滚不会影响外部事务的状态。
NESTED 和 REQUIRES_NEW 的区别在于,NESTED 是外部事务的一部分,而 REQUIRES_NEW 是完全独立于外部事务的一个新事务。
总结 :NESTED 是一种用于嵌套事务的事务传播行为,它允许在外部事务的范围内开启一个独立的嵌套事务,并可以独立提交或回滚。这使得嵌套事务可以在外部事务的保护下进行,同时又能保持一定的独立性