Spring框架中定义了七种事务传播行为。这些行为定义了事务应该如何传播,例如:在一个事务内部的方法中调用另一个方法,两个方法是否应该运行在同一个事务上下文中,还是每个方法应该有自己的事务上下文。Spring的事务传播行为定义在org.springframework.transaction.TransactionDefinition接口中:
-
PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 -
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。 -
PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。 -
PROPAGATION_REQUIRES_NEW:新建事务,如果当前在事务中,把当前事务挂起。 -
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 -
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。 -
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
以下是如何在代码中声明这些行为的例子:
@Service
public class MyService {
@Transactional(propagation = Propagation.REQUIRED)
public void method1() {
//...
}
@Transactional(propagation = Propagation.SUPPORTS)
public void method2() {
//...
}
@Transactional(propagation = Propagation.MANDATORY)
public void method3() {
//...
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void method4() {
//...
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void method5() {
//...
}
@Transactional(propagation = Propagation.NEVER)
public void method6() {
//...
}
@Transactional(propagation = Propagation.NESTED)
public void method7() {
//...
}
}
以下是关于每种传播行为可能适用的场景:
-
PROPAGATION_REQUIRED:这是最常用的传播行为,适用于大多数事务环境。如订单处理,需要保证各个步骤的一致性,商品减库存,生成订单等操作需要在同一个事务内完成。 -
PROPAGATION_SUPPORTS:对于一些读取数据的操作,如果当前有事务就使用,没有也没关系。例如,读取配置信息,如果有事务就利用现有的,如果没有就按照非事务方式执行。 -
PROPAGATION_MANDATORY:这种传播行为适用于必须在一个已存在的事务中执行的业务场景,否则应该抛出异常。比如,某个步骤必须是由另外一个步骤在同一个事务中调用的。 -
PROPAGATION_REQUIRES_NEW:每次都创建一个新的事务,适用于需要保证与外部事务无关的场景,比如日志记录。无论外部事务是否存在或者如何结束,日志记录总是需要被完成的。 -
PROPAGATION_NOT_SUPPORTED:对于那些即使有事务存在,也不能在事务中执行的操作,比如某些特殊的系统命令,或者是与第三方系统交互的操作。 -
PROPAGATION_NEVER:对于不需要事务管理的读操作,可以使用此传播行为。 -
PROPAGATION_NESTED:适用于如果当前主事务回滚,内部嵌套事务也需要回滚,而内部事务可以独立提交不影响其他事务。注意,这需要特定的事务管理器支持。