Spring Transaction - 在特定方法下不回滚错误
Posted
技术标签:
【中文标题】Spring Transaction - 在特定方法下不回滚错误【英文标题】:Spring Transaction - Do not rollback for error under specific method 【发布时间】:2022-01-20 08:20:21 【问题描述】:我有一个 Spring Boot 应用程序,其中一个服务负责创建一个业务实体。为简单起见,让我们考虑:
create(Object toCreate)
validationService.validate(toCreate);
Object created = repository.save(toCreate);
notificationService.notify(created);
业务发生了变化,现在我希望创建如果通知失败也不会失败。
因此,我将notify()
方法包装在一个仅记录错误的try-catch
块中(即RuntimeException
)。
但是,在测试时,抛出了事务回滚错误,表示连接已关闭。我不希望任何回滚,尤其是因为 NotificationService
不会修改数据库。
我如何告诉 Spring 在 NotificationService
中发生的任何异常都很好并且不需要回滚?我尝试用@Transactional(propagation=NEVER)
注释类/方法,但得到existing transaction found for transaction marked with propagation 'never'
【问题讨论】:
【参考方案1】:也许重构代码比引入更复杂的事务处理更有帮助。
假设您的 @Transactional
在 create()
方法上,我们可以看到您有:
-
预持久化业务逻辑
持久化逻辑
持久化后业务逻辑
这取决于您的用例,但我不希望得到分数。 1 & 3 包含持久性逻辑。如果是这种情况,您可以在它自己的服务中提取持久性逻辑,该服务本身就是一个事务,而不是父级。
如果您需要在这些步骤中进行交易,您也可以在他们自己的交易中提取它们。
其他潜在客户可能是:
-
default rollback behavior is for runtime unchecked exceptions。您可以使用已检查的异常来避免回滚。
如果您的通知与持久性分开并且您不关心事务,则可以将其设为异步调用(例如使用
@Async
)。它将在事务之外在其自身的上下文中安排。
【讨论】:
【参考方案2】:您可以使用 @Transactional 的 norollbackfor 选项,因此您必须指定一个异常类而不是服务,并且当通知中发生错误时,尝试抛出一个不会导致回滚的特定错误。
【讨论】:
您能提供更多信息吗?这个“@Transactional”应该在哪里? 是的,抱歉。你应该把 @Transactional(norollbackfor = exception.class) 放在你的函数上。不是你的班级。 但是使用哪种方法?创建还是通知?如果是在创建中,如果在验证和通知中都可以抛出相同的错误,但我只想忽略内部通知? 关于你的创建方法。您必须在通知方法中管理可能发生的错误。使用尝试捕获。然后,您可以在通知方法中可能发生的每个错误中抛出一个特定的错误。以上是关于Spring Transaction - 在特定方法下不回滚错误的主要内容,如果未能解决你的问题,请参考以下文章
java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()L
Spring Transaction:如果我不在方法上给出@Transaction 注释会发生啥
Spring Boot Stomp-Transaction Sockjs: ERROR message=[Bad transaction] Invalid transaction identifier