StaleObjectStateException:Grails中的事务错误

Joh*_*tta 2 grails hibernate grails-orm

我有一个TaskList实体,有许多可行的Task实体,某些任务可以"关闭"TaskList.

class TaskList {
    ...
    static hasMany = [
        tasks: Task
    ]
}

class Task {
    ...
    static belongsTo = [taskList: TaskList]
}
Run Code Online (Sandbox Code Playgroud)

现在当一个Task更新并且它可以 "关闭"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)
}
Run Code Online (Sandbox Code Playgroud)

我的问题是当用户在TaskListService更新它时更新TaskList实体.

class TaskListController {
    def update () {
        TaskList taskListInstance = TaskList.get(params.id)
        //... do some stuff
        taskListInstance.properties = params
        taskListInstance.save(flush:true)
    }
}
Run Code Online (Sandbox Code Playgroud)

org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或unsaved-value映射不正确):[com.giotta.TaskList#1]

如何避免此版本冲突?

Bur*_*ith 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)
}
Run Code Online (Sandbox Code Playgroud)

我在这里使用taskListId动态属性.您可能需要将其更改为taskInstance.taskList.id