Spring框架中的7大神秘事务策略 - 程序员古德
Spring定义了七种事务传播规则,确保方法在不同事务上下文中的执行方式。其中,REQUIRED最为常用,保证数据一致性;SUPPORTS适应有无事务环境;MANDATORY强制事务执行;REQUIRES_NEW独立新事务;NOT_SUPPORTED和NEVER分别避免和禁止事务;NESTED允许嵌套子事务。选择适当规则,确保数据完整性、一致性,提升系统健壮性。
Spring框架中的7大神秘事务策略 - 程序员古德
PROPAGATION_REQUIRED
这是最最最常用的方式。这是最最最常用的方式。这是最最最常用的方式。
如果当前存在事务,则加入该事务;如果当前没有事务,就新建一个事务。这是最常用的选择,它可以确保被调用方法运行在同一个事务上下文中,从而保持数据的一致性。
例如,在订单处理中,当用户下订单后需要减库存和增加订单记录。这两个操作必须同时成功或失败,以确保数据的一致性。通过PROPAGATION_REQUIRED,这两个操作可以在同一个事务中执行。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.stereotype.Repository;
@Repository
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.REQUIRED)
publicvoidmethodB() {
System.out.println("Method B started");
// 执行一些业务逻辑,可能涉及数据库操作
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}
@Transactional(propagation = Propagation.REQUIRED)
publicvoidmethodA() {
System.out.println("Method A started");
methodB(); // 在methodA()中调用methodB()
System.out.println("Method A completed successfully");
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
@RestController
publicclassMyController{
@Autowired
privateMyService myService;
@GetMapping("/execute")
publicStringexecute() {
myService.methodA(); // 调用Service类中的methodA()方法,它将进一步调用methodB()方法
return"Execution completed";
}
}
在这个示例中,MyService类中的methodA()和methodB()都使用了PROPAGATION_REQUIRED传播规则。
这意味着它们将加入当前存在的事务,如果不存在事务,它们将创建一个新的事务。当MyController类中的execute()方法被调用时,它将调用MyService类中的methodA()方法,然后methodA()方法将调用methodB()方法。如果任何一个方法执行失败并抛出异常,整个事务将回滚。
PROPAGATION_SUPPORTS
如果当前存在事务,则加入该事务;如果当前没有事务,就以非事务的方式继续运行。这主要用于那些可以在事务中运行,但也可以单独运行的操作。
例如,日志记录功能,该功能可以在事务中记录操作,但如果没有事务,它仍然可以记录。这种情况下可以使用PROPAGATION_SUPPORTS。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.SUPPORTS)
publicvoidmethodB() {
System.out.println("Method B started");
// 执行一些业务逻辑,可能涉及数据库操作
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}
@Transactional(propagation = Propagation.SUPPORTS)
publicvoidmethodA() {
System.out.println("Method A started");
methodB(); // 在methodA()中调用methodB()
System.out.println("Method A completed successfully");
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
@RestController
publicclassMyController{
@Autowired
privateMyService myService;
@GetMapping("/execute")
publicStringexecute() {
myService.methodA(); // 调用Service类中的methodA()方法
return"Execution completed";
}
}
在这个示例中,MyService类中的methodA()和methodB()都使用了PROPAGATION_SUPPORTS传播规则。这意味着如果当前存在事务,那么它们将加入该事务;如果不存在事务,它们将以非事务方式执行。当MyController类中的execute()方法被调用时,它将调用MyService类中的methodA()方法,然后methodA()方法将调用methodB()方法。
PROPAGATION_MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,就抛出异常。这确保了方法只能在事务上下文中运行。
例如,某个操作只能在事务中进行以确保数据的完整性。如果该操作在非事务上下文中被调用,就会抛出异常。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.stereotype.Repository;
@Repository
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
importorg.springframework.transaction.TransactionSystemException;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.MANDATORY)
publicvoidmethodB() {
System.out.println("Method B started");
// 执行一些业务逻辑,可能涉及数据库操作
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}
@Transactional(propagation = Propagation.MANDATORY)
publicvoidmethodA() {
System.out.println("Method A started");
try{
methodB(); // 在methodA()中调用methodB()
System.out.println("Method A completed successfully");
}catch(TransactionSystemException e) {
System.out.println("Transaction not active, cannot call methodB() from methodA()");
throwe;
}
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.TransactionTemplate;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@RestController
publicclassMyController{
@Autowired
privateMyService myService;
@Autowired
privateTransactionTemplate transactionTemplate;
@GetMapping("/execute")
publicStringexecute() {
DefaultTransactionDefinition def =newDefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 设置事务传播行为为REQUIRES_NEW,确保在调用methodA()时存在活动事务。
transactionTemplate.execute(def, status -> {
myService.methodA(); // 调用Service类中的methodA()方法,它将进一步调用methodB()方法。这里使用TransactionTemplate确保存在活动事务。
returnnull; // 事务执行完成,返回null。实际项目中可能需要根据需求返回合适的值。
});
return"Execution completed";
}
}
在这个示例中,MyService类中的methodA()和methodB()都使用了PROPAGATION_MANDATORY传播规则。这意味着它们必须在已经存在的事务上下文中执行。如果调用它们时没有活动的事务,将会抛出TransactionSystemException异常。
PROPAGATION_REQUIRES_NEW
新建一个事务,如果当前存在事务,把当前事务挂起。这可以确保被调用方法在新的独立事务中运行,与调用者的事务隔离。
例如,用户注册后需要发送欢迎邮件。即使注册失败,邮件仍然应该发送。通过PROPAGATION_REQUIRES_NEW,发送邮件的操作可以在一个新的事务中进行,不受注册事务的影响。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.stereotype.Repository;
@Repository
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
publicvoidmethodB() {
System.out.println("Method B started");
// 执行一些业务逻辑,可能涉及数据库操作
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
publicvoidmethodA() {
System.out.println("Method A started");
try{
methodB(); // 在methodA()中调用methodB()
System.out.println("Method A completed successfully");
}catch(Exception e) {
System.out.println("An error occurred while executing methodB() from methodA()");
throwe;
}
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.TransactionCallbackWithoutResult;
importorg.springframework.transaction.support.TransactionTemplate;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@RestController
publicclassMyController{
@Autowired
privateMyService myService;
@GetMapping("/execute")
publicStringexecute() {
myService.methodA(); // 调用Service类中的methodA()方法,它将进一步调用methodB()方法。由于使用了PROPAGATION_REQUIRES_NEW,每次调用都会启动一个新的事务。
return"Execution completed"; // 执行完成,返回字符串。实际项目中可能需要根据需求返回合适的值。
}
}
在这个示例中,MyService类中的methodA()和methodB()都使用了PROPAGATION_REQUIRES_NEW传播规则。这意味着每次调用这些方法时,无论是否已经存在事务,都会启动一个新的事务。请注意,PROPAGATION_REQUIRES_NEW会挂起当前事务(如果存在),并创建一个新的事务。新的事务将独立于原始事务进行提交或回滚。调用结束后,原始事务将继续执行。这样确保了每个方法调用都在独立的事务中执行,互不影响。
PROPAGATION_NOT_SUPPORTED
如果当前存在事务,就把当前事务挂起。这主要用于那些不应该在事务中运行的操作。这种传播行为意味着目标方法将在没有事务的情况下运行,即使调用者方法处于事务上下文中。这可以用于在事务的边界内执行一些非事务性的操作,或者临时跳出事务以执行特定的代码逻辑。
例如,某个长时间的报告生成操作不应该在事务中运行,以免影响其他操作的性能。这种情况下可以使用PROPAGATION_NOT_SUPPORTED。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.stereotype.Repository;
@Repository
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.NOT_SUPPORTED)
publicvoidmethodB() {
System.out.println("Method B started");
// 执行一些业务逻辑,可能涉及数据库操作,但由于使用了PROPAGATION_NOT_SUPPORTED,该操作将在非事务环境中执行。
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}
@Transactional(propagation = Propagation.REQUIRED) // 使用默认的REQUIRED传播规则,确保methodA()在事务环境中执行。
publicvoidmethodA() {
System.out.println("Method A started");
try{
methodB(); // 在methodA()中调用methodB()。由于methodB()使用了PROPAGATION_NOT_SUPPORTED,它将在非事务环境中执行。
System.out.println("Method A completed successfully");
}catch(Exception e) {
System.out.println("An error occurred while executing methodB() from methodA()");
throwe;
}
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.TransactionCallbackWithoutResult;
importorg.springframework.transaction.support.TransactionTemplate;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@RestController
publicclassMyController{
@AutowiredprivateMyService myService;
@GetMapping("/execute")
publicStringexecute() {
/*
调用Service类中的methodA()方法,它将进一步调用methodB()方法,由于使用了PROPAGATION_NOT_SUPPORTED,methodB()将在非事务环境中执行。
而methodA()使用默认的REQUIRED传播规则,确保它在事务环境中执行。
这样可以在同一个方法中实现事务和非事务操作的混合执行。
*/
myService.methodA();
return"Execution completed";
}
}
思考:
1、那PROPAGATION_NOT_SUPPORTED和PROPAGATION_NEVER有什么区别:
PROPAGATION_NOT_SUPPORTED:
当使用PROPAGATION_NOT_SUPPORTED传播规则时,如果当前存在事务,则挂起该事务,并在没有事务的上下文中执行目标方法。如果当前没有事务,则目标方法仍然在没有事务的上下文中执行。
这种传播行为意味着目标方法将在没有事务的情况下运行,即使调用者方法处于事务上下文中。这可以用于在事务的边界内执行一些非事务性的操作,或者临时跳出事务以执行特定的代码逻辑。
PROPAGATION_NEVER:
当使用PROPAGATION_NEVER传播规则时,如果当前存在事务,则抛出异常。该方法只能在没有事务的上下文中执行,如果调用者方法处于事务上下文中,将会引发异常。
这种传播行为强制要求目标方法在没有事务的情况下运行,如果当前存在事务,则会中断调用并抛出异常。这可以用于确保某些特定的代码逻辑不会在事务上下文中执行,以避免潜在的事务管理问题。
综上所述,PROPAGATION_NOT_SUPPORTED和PROPAGATION_NEVER的主要区别在于它们对当前存在的事务的处理方式。PROPAGATION_NOT_SUPPORTED会挂起当前事务并在没有事务的上下文中执行目标方法,而PROPAGATION_NEVER则会检查当前是否存在事务,如果存在则抛出异常。
PROPAGATION_NEVER
以非事务方式运行,如果当前存在事务,则抛出异常。这确保了方法永远不会在事务上下文中运行。
考虑一个性能测试的操作,该操作不应该受到任何事务的约束。如果该操作在事务中被调用,就应该抛出异常。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.stereotype.Repository;
@Repository
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
importorg.springframework.transaction.UnexpectedRollbackException;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.NEVER)
publicvoidmethodB() {
System.out.println("Method B started");
try{
// 尝试执行一些业务逻辑,但由于使用了PROPAGATION_NEVER,如果当前存在事务,则会抛出UnexpectedRollbackException异常。
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}catch(UnexpectedRollbackException e) {
System.out.println("An UnexpectedRollbackException occurred while executing methodB() because it was called within an existing transaction.");
throwe;
}
}
@Transactional(propagation = Propagation.REQUIRED) // 使用默认的REQUIRED传播规则,确保methodA()在事务环境中执行。
publicvoidmethodA() {
System.out.println("Method A started");
try{
methodB(); // 在methodA()中调用methodB()。由于methodB()使用了PROPAGATION_NEVER,它将尝试在非事务环境中执行,但如果已经存在一个事务,将会抛出UnexpectedRollbackException异常。
System.out.println("Method A completed successfully");
}catch(Exception e) {
System.out.println("An error occurred while executing methodB() from methodA()");
throwe;
}
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.TransactionCallbackWithoutResult;
importorg.springframework.transaction.support.TransactionTemplate;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@RestController
publicclassMyController{
@AutowiredprivateMyService myService;
@GetMapping("/execute")
publicStringexecute() {
/*
调用Service类中的methodA()方法,它将进一步调用methodB()方法。
由于methodB()使用了PROPAGATION_NEVER,如果当前存在事务,methodB()将抛出UnexpectedRollbackException异常。
*/
myService.methodA();
}
}
在上面的代码中,methodB()使用PROPAGATION_NEVER传播规则,这意味着它应该在非事务环境中执行。但是,如果它已经在一个事务中(由methodA()的REQUIRED传播规则确保),那么它会抛出UnexpectedRollbackException异常。
以下是几个约束点:
methodA()使用REQUIRED传播规则,确保它在事务中执行。
methodB()使用PROPAGATION_NEVER传播规则,试图在非事务环境中执行。如果它已经在一个事务中,就会抛出异常。
所以,如果methodA()被调用并且已经存在一个事务(由其他方法或外部因素引起),那么当methodB()被调用时,它会抛出UnexpectedRollbackException异常。这是因为PROPAGATION_NEVER的规则是不允许在已经存在的事务中执行的。
PROPAGATION_NESTED
如果当前存在事务,则嵌套事务作为一个子事务运行;如果当前没有事务,则该嵌套事务即表现为REQUIRED属性。这允许在一个已存在的事务中创建一个新的嵌套事务,这个嵌套事务可以独立于父事务进行提交或回滚。
例如:在订单处理中,用户下订单后除了减库存和增加订单记录外,还需要更新用户的积分,积分更新操作可以作为一个嵌套事务执行,这样即使积分更新失败,也不会影响到订单的处理。
1、Repository类(MyRepository.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.stereotype.Repository;
@Repository
publicinterfaceMyRepositoryextendsJpaRepositoryMyEntity,Long> {
// 添加适合您项目的JPA存储库方法
}
2、Service类(MyService.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Propagation;
importorg.springframework.transaction.annotation.Transactional;
@Service
publicclassMyService{
@Autowired
privateMyRepository myRepository;
@Transactional(propagation = Propagation.NESTED)
publicvoidmethodB() {
System.out.println("Method B started");
try{
// 尝试执行一些业务逻辑,由于使用了PROPAGATION_NESTED,它将参与父事务,或者如果父事务不存在,则创建新的事务。
myRepository.updateData("Method B");
System.out.println("Method B completed successfully");
}catch(Exception e) {
System.out.println("An error occurred while executing methodB()");
throwe;
}
}
@Transactional(propagation = Propagation.REQUIRED) // 使用默认的REQUIRED传播规则,确保methodA()在事务环境中执行。
publicvoidmethodA() {
System.out.println("Method A started");
try{
methodB(); // 在methodA()中调用methodB()。由于methodB()使用了PROPAGATION_NESTED,它将参与methodA()所在的事务,或者如果methodA()所在的事务不存在,则创建新的事务。这样可以在同一个方法中实现嵌套事务。
System.out.println("Method A completed successfully");
}catch(Exception e) {
System.out.println("An error occurred while executing methodB() from methodA()");
throwe;
}
}
}
3、Controller类(MyController.java)
/**
* @版权 Copyright by 程序员古德
* @创建人 程序员古德
* @创建时间 2023/09/12 15:37
*/
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.TransactionCallbackWithoutResult;
importorg.springframework.transaction.support.TransactionTemplate;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@RestController
publicclassMyController{
@AutowiredprivateMyService myService;
@GetMapping("/execute")
publicStringexecute() {
/*
调用Service类中的methodA()方法,它将进一步调用methodB()方法。由于使用了PROPAGATION_NESTED,如果methodA()所在的事务存在,则methodB()将参与该事务;否则,它将创建新的事务。
*/
myService.methodA();
}
}
思考:
1、PROPAGATION_NESTED和PROPAGATION_REQUIRED有什么区别?
PROPAGATION_NESTED和PROPAGATION_REQUIRED都是Spring框架中事务传播行为的选项,它们在事务处理方面有一些区别:
事务存在性:
PROPAGATION_REQUIRED:如果当前没有事务,则新建一个事务;如果当前存在事务,则加入该事务。
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
嵌套事务:
PROPAGATION_NESTED允许在父事务中执行子事务,形成一个嵌套事务。子事务可以独立于父事务进行提交或回滚,而父事务不受子事务的影响。这种传播行为要求数据库和JDBC驱动程序支持保存点(Savepoint)功能,以便能够在嵌套事务中进行回滚操作。
PROPAGATION_REQUIRED不支持嵌套事务的概念。如果当前存在事务,则该方法将加入该事务;否则,将新建一个事务。它没有提供像PROPAGATION_NESTED那样的子事务独立提交或回滚的能力。
综上所述,PROPAGATION_NESTED和PROPAGATION_REQUIRED的主要区别在于嵌套事务的处理。PROPAGATION_NESTED允许在父事务中执行子事务,并提供子事务的独立提交或回滚能力;而PROPAGATION_REQUIRED则不支持嵌套事务的概念,只能加入当前存在的事务或新建一个事务。在选择传播行为时,应根据具体的业务需求和数据库支持来确定使用哪种传播规则。如果用父、子事务场景来说:父事务回滚的同时子事务也会回滚,子事务回滚但不影响父事务提交。
核心总结
Spring定义了七种事务传播规则,确保方法在不同事务上下文中的执行方式。其中,REQUIRED最为常用,保证数据一致性;SUPPORTS适应有无事务环境;MANDATORY强制事务执行;REQUIRES_NEW独立新事务;NOT_SUPPORTED和NEVER分别避免和禁止事务;NESTED允许嵌套子事务。选择适当规则,确保数据完整性、一致性,提升系统健壮性。
领取专属 10元无门槛券
私享最新 技术干货