首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【揭秘】Spring框架中的7大神秘事务策略,你了解多少?

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允许嵌套子事务。选择适当规则,确保数据完整性、一致性,提升系统健壮性。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OdXj0UU386Kli8St1buGu7jQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券