StaleObjectStateException:Grails中的事务错误

时间:2013-02-06 19:49:41

标签: hibernate grails gorm

我有一个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]

如何避免此版本冲突?

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