我有一个TaskList实体,有许多可行的Task实体,某些任务可以“关闭”TaskList。
class TaskList {
...
static hasMany = [
tasks: Task
]
}
class Task {
...
static belongsTo = [taskList: TaskList]
}
现在,当任务更新并且可以“关闭”TaskList时,我会TaskListService
拨打closeList()
class TaskListService {
def closeList(TaskList taskList) {
taskList.status = "CLOSED"
taskList.save()
}
}
// TaskController pseudo-update
def update () {
Task taskInstance = Task.get(params.id)
//... do something with the taskInstance
taskListService.closeList(taskInstance.taskList)
}
我的问题是用户在TaskListService
正在更新时更新TaskList实体。
class TaskListController {
def update () {
TaskList taskListInstance = TaskList.get(params.id)
//... do some stuff
taskListInstance.properties = params
taskListInstance.save(flush:true)
}
}
org.hibernate.StaleObjectStateException:行已被另一个事务更新或删除(或未保存的值映射不正确):[com.giotta.TaskList#1]
如何避免此版本冲突?
答案 0 :(得分:8)
如果您希望进行并发编辑,则必须使用显式锁定。你正在使用乐观锁定,因为当你希望没有并发编辑时使用乐观锁定,并且在极少数情况下你可以解决这个问题。
使用lock()
方法代替get()
方法,然后执行更新。请注意,锁定仅在事务中有意义,因此将id传递给服务而不是整个实例。
class TaskListService {
def closeList(long taskListId) {
TaskList taskList = TaskList.lock(taskListId)
taskList.status = "CLOSED"
taskList.save()
}
}
// TaskController pseudo-update
def update () {
Task taskInstance = Task.get(params.id)
//... do something with the taskInstance
taskListService.closeList(taskInstance.taskListId)
}
这里我使用taskListId
动态属性。您可能需要将其更改为taskInstance.taskList.id