我引入了一个TransactionService,我在控制器中使用它来执行乐观事务。它应该
它基本上是这样的:
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并在某个阶段中止,但这并不重要。它是从传递事务的控制器调用的,以便作为闭包安全地执行。
我的问题:当服务由于并发更新而遇到org.hibernate.StaleObjectStateException时,它会再次尝试,但异常永远不会消失。
我已经尝试了不同的东西,例如在控制器传递的事务中重新附加域类,清除服务或控制器中的会话,但它没有帮助。我错过了什么?
我应该注意到,当我尝试在使用status.createSavepoint()调用transaction()之前插入savePoint时,我的“事务管理器不允许嵌套事务”出错。我试过这个,因为我还怀疑错误存在,因为事务从控制器传递到服务,我需要启动一个新的/嵌套事务来避免它,但是因为错误显示这在我的情况下是不可能的。
或者可能是将事务作为关闭问题传递出来的?
我假设.withTransaction之前使用的域类无关紧要,或者是吗?
答案 0 :(得分:1)
它不是闭包本身,但我相信transaction
内部有一些陈旧的变量引用。
如果您尝试仅传递在执行时重新读取其对象的闭包,该怎么办?像
executeOptimisticTransaction {
Something some = Something.get(id)
some.properties = aMap
some.save()
}
我不认为在没有在Hibernate中重新读取对象的情况下“刷新”对象是不可能的。
是的,你打电话给.withTransaction()的班级无关紧要。
对于更新计算总计/评级的示例,这是一个问题本身的数据重复。我宁愿:
Book.executeQuery('update Rating set rating=xxx')
将使用最新的评级。如果您正在为重负载进行优化,那么无论如何都不会以Groovy方式执行所有操作。不要在Grails中保存Rating对象,只能阅读它们。