我介绍了一个TransactionService,我在 Controller 中使用它来执行乐观交易。这应该
基本上看起来像这样:
class TransactionService {
transactional = false // Because withTransaction is used below anyway
def executeOptimisticTransaction(Closure transaction) {
def success = false
while (!success) {
anyDomainClass.withTransaction { status ->
try {
transaction()
success = true
} catch(Exception e) {
status.setRollbackOnly()
}
}
}
}
}
它稍微复杂一点,例如它在再次尝试之前使用不同的Thread.sleeps,并在某个阶段中止,但这并不重要。它由传递事务的 Controller 调用,以作为闭包安全地执行。
我的问题:当服务由于并发更新而遇到org.hibernate.StaleObjectStateException时,它将继续尝试,但该异常永不消失。
我已经尝试过其他方法,例如在 Controller 传递的事务中重新附加域类,清除服务或 Controller 中的 session ,但这无济于事。我想念什么?
我应该注意,当我尝试使用status.createSavepoint()调用transaction()之前插入一个savePoint时,出现了一个错误,即“Transaction Manager不允许嵌套事务”。我尝试此操作是因为我还怀疑该错误存在,因为该事务已从 Controller 传递到服务,并且我需要启动一个新的/嵌套事务来避免它,但是由于错误显示在我的情况下这是不可能的。
还是将交易作为关闭传递是问题所在?
我假设.withTransaction之前使用的域类无关紧要,还是那样?
最佳答案
它不是闭包本身,但我相信transaction
里面有一些过时的变量引用。
如果您尝试只传递在执行时重新读取其对象的闭包怎么办?喜欢
executeOptimisticTransaction {
Something some = Something.get(id)
some.properties = aMap
some.save()
}
我认为在不重新休眠的情况下“刷新”对象是不可能的。
是的,在什么类上调用.withTransaction()都没有关系。
对于更新计算的总数/额定值的示例,这是一个数据重复,这本身就是一个问题。我宁愿:
Book.executeQuery('update Rating set rating=xxx')
。如果您正在针对重载进行优化,那么无论如何您将不会做任何Groovy方式。不要将Rating对象保存在Grails中,只能阅读它们。 关于hibernate - 如何克服Grails Service中的StaleObjectStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4375757/