gpt4 book ai didi

exception - Grails UnexpectedRollbackException发生: Not Sure Why

转载 作者:行者123 更新时间:2023-12-04 03:45:04 26 4
gpt4 key购买 nike

我有以下代码:

class ServiceA {

def save(Object object) {
if (somethingBadComesBack) {
throw new CustomRuntimeException(data)
}
}
}

class ServiceB {

def serviceA

def save(Object object) {
try {
serviceA.save(object)
// do more stuff if good to go
} catch(CustomRuntimeException e) {
// populate some objects with errors based on exception
}
}
}

class ServiceC {

def serviceB

def process(Object object) {
serviceB.save(object)
if (object.hasErrors() {
// do some stuff
}else{
// do some stuff
}

def info = someMethod(object)
return info
}
}

class SomeController {

def serviceC

def process() {

def object = .....
serviceC.save(object) // UnexpectedRollbackException is thrown here

}
}

调用 ServiceA.save()并发生异常时, ServiceC.save()尝试返回时会抛出 UnexpectedRollbackException

我做了以下事情:
try {
serviceC.process(object)
}catch(UnexpectedRollbackException e) {
println e.getMostSpecificCause()
}

我得到:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

我不确定从哪里开始寻找解决方法。

最佳答案

您正在使用运行时异常来回滚事务,但这是作弊-它利用了副作用。运行时异常会自动回滚事务,因为您不需要捕获它们,因此假定如果引发了异常,则不会发生,默认行为是回滚。您可以将方法配置为不为特定的预期运行时异常回滚,但这很少见。被检查的异常不会回滚异常,因为在Java中必须捕获它们或在throws中声明它们,因此您必须显式地抛出它或将其隐藏。无论哪种方式,您都有机会再试一次。

正确回滚事务的正确方法是在当前setRollbackOnly()上调用TransactionStatus,但这不能在服务方法中直接访问(由于它是闭包的参数,因此在withTransaction块中)。但是很容易做到:导入org.springframework.transaction.interceptor.TransactionAspectSupport并调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。这将需要您对代码进行重新处理,因为不会捕获任何异常,因此您需要检查它是否已使用TransactionAspectSupport.currentTransactionStatus().isRollbackOnly()回滚。

我不确定这是Grails的问题还是标准行为,但是在进行调试时,使用3个不同的TransactionStatus实例进行了3次commit调用。只有第一个设置了回滚标志,但是第二个知道了第一个并且还可以。第三个被认为是新事务,并且触发了您所看到的相同异常。因此,要解决此问题,我将其添加到了第二和第三服务方法中:

def status = TransactionAspectSupport.currentTransactionStatus()
if (!status.isRollbackOnly()) status.setRollbackOnly()

链接回滚标志。那行得通,我没有得到 UnexpectedRollbackException

将其与检查的异常结合起来可能会更容易。它仍然过于昂贵,因为它将不必要地填充stacktrace,但是如果您调用 setRollbackOnly()并抛出一个已检查的异常,那么您将能够使用与现在相同的常规工作流程。

关于exception - Grails UnexpectedRollbackException发生: Not Sure Why,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13482103/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com