Spring事务的传播行为(Propagation Behavior)描述了在多个事务之间如何进行协调和交互。它定义了在一个事务方法被另一个事务方法调用时,事务应该如何传播。在Spring中,传播行为被定义为一组预定义的值,这些值描述了事务在方法调用链中的行为。
以下是Spring支持的事务传播行为的类型:
这些传播行为可以帮助你更好地控制和管理你的事务。例如,如果你希望在某个特定的方法调用时总是开启新的事务,你可以将该方法的事务传播行为设置为PROPAGATION_REQUIRES_NEW。同样,如果你希望在某些情况下以非事务方式运行代码,你可以将该代码块的事务传播行为设置为PROPAGATION_NOT_SUPPORTED。
以下是几个Spring事务传播行为的例子:
PROPAGATION_REQUIRED
例子:@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
serviceB.methodB();
}
}
PROPAGATION_SUPPORTS
例子:@Service
public class ServiceB {
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
// 该方法将以非事务方式执行,如果存在事务,就加入该事务
}
}
PROPAGATION_MANDATORY
例子:@Service
public class ServiceB {
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
// 该方法必须在一个事务中执行,如果没有事务,就会抛出异常
}
}
PROPAGATION_REQUIRES_NEW
例子:@Service
public class ServiceB {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 该方法将创建一个新的事务,并挂起当前事务
}
}
PROPAGATION_NOT_SUPPORTED
例子:@Service
public class ServiceB {
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
// 该方法以非事务方式执行,如果存在事务,就把当前事务挂起
}
}
PROPAGATION_NEVER
例子:@Service
public class ServiceB {
@Transactional(propagation = Propagation.NEVER)
public void methodB() {
// 该方法以非事务方式执行,如果存在事务,就抛出异常
}
}
PROPAGATION_NESTED
例子:@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
@Transactional(propagation = Propagation.NESTED)
public void methodA() {
serviceB.methodB();
}
}
在Spring中,serviceA是否有事务主要取决于两点:
@Transactional
注解:如果在serviceA类上添加了@Transactional注解,那么该类中的所有方法都将具有事务。@Transactional
注解:如果在serviceA类中的某个方法上添加了@Transactional注解,那么只有这个方法具有事务。如果没有上述的任何一种情况,那么默认情况下,serviceA将不会有事务。
需要注意的是,事务传播是在方法调用时发生的,因此在一个事务中的方法调用另一个没有事务的方法时,将会根据@Transactional注解的设置来决定是否创建新的事务。如果被调用的方法有@Transactional注解,并且其传播属性设置为PROPAGATION_REQUIRED或更高,那么调用该方法的方法将在一个新的事务中执行。如果被调用的方法没有事务,那么调用该方法的方法将在其自身的事务中执行。
假设我们有一个ServiceA,它有两个方法:methodA()和methodB()
@Service
@Transactional
public class ServiceA {
// methodA() and methodB()
}
这意味着ServiceA类中的所有方法都将具有事务。因此,当调用methodA()或methodB()时,它们将在事务中执行。
@Service
public class ServiceA {
@Transactional
public void methodA() {
// 该方法将在事务中执行
}
public void methodB() {
// 该方法默认情况下不在事务中执行
}
}
在这种情况下,只有methodA()具有事务。因此,当调用methodA()时,它将在事务中执行。但是,调用methodB()时,它默认情况下不在事务中执行。
需要注意的是,事务传播是在方法调用时发生的。在一个事务中的方法调用另一个没有事务的方法时,将会根据@Transactional注解的设置来决定是否创建新的事务。例如,如果methodA()在一个事务中调用methodB(),而methodB()没有事务,那么根据@Transactional注解的设置,methodB()将在自己的事务中执行,或者与methodA()的事务共享数据(如果@Transactional注解的传播属性设置为PROPAGATION_NESTED)。
methodA()调用methodB()时,如何让methodB()以非事务执行
要让methodB()以非事务执行,可以通过设置@Transactional注解的propagation属性为Propagation.NON_TRANSACTIONAL来实现。这样,当methodA()调用methodB()时,methodB()将以非事务方式执行。
@Service
public class ServiceA {
@Transactional
public void methodA() {
methodB();
}
@Transactional(propagation = Propagation.NON_TRANSACTIONAL)
public void methodB() {
// 该方法将以非事务方式执行
}
}
在上面的代码中,methodA()是一个有事务的方法,而methodB()的@Transactional注解将传播属性设置为Propagation.NON_TRANSACTIONAL,表示它将以非事务方式执行。因此,当methodA()调用methodB()时,methodB()将以非事务方式执行。