Hibernate Grails控制器以任何方式保存域项
使用Grails2.3.9 在控制器中,我执行一些检查,当失败时返回自定义错误响应。以下是一段代码片段:Hibernate Grails控制器以任何方式保存域项,hibernate,grails,grails-controller,Hibernate,Grails,Grails Controller,使用Grails2.3.9 在控制器中,我执行一些检查,当失败时返回自定义错误响应。以下是一段代码片段: def update() { def instance = Group.get(params.groupId) instance.properies = params if (instance.hasErrors()) { // going through here: instance is not saved respond ins
def update() {
def instance = Group.get(params.groupId)
instance.properies = params
if (instance.hasErrors()) {
// going through here: instance is not saved
respond instance.errors, view:'edit'
return
}
// do custom checks
if(checksFailed) {
// instance is saved anyways :(
instance.discard()
response.sendError(response.SC_CONFLICT)
return
}
instance.save flush:true
// ... respond success
}
当检查失败时,我的错误响应将按我的要求返回。但是,无论如何都会保存实例(未到达instance.save
)。如何使Grails/Hibernate知道不保存此实例
另一种方法可能是断开实例与Hibernate会话的连接。在Grails中,我该怎么做
更新:在域实例搭建的控制器中,instance.discard()
技巧可以工作:
def update(Group groupInstance) {
if (groupInstance.hasErrors()) {
// going through here: instance is not saved
respond instance.errors, view:'edit'
return
}
// do custom checks
if(checksFailed) {
// instance is not saved
groupInstance.discard()
response.sendError(response.SC_CONFLICT)
return
}
groupInstance.save flush:true
// ... respond success
}
我发现很难理解为什么它在一种情况下有效而在另一种情况下无效。最好的方法不是使用discard(),而是使用事务和数据库的本机事务功能。我建议将逻辑移动到服务中(分离控制器流代码和应用程序的逻辑)。示例:
class GroupService {
@Transactional
void updateBook(params) {
....
// do custom checks
if(checksFailed) {
status.setRollbackOnly() // rollback transaction
}
else {
instance.save flush:true
}
}
}
您可以对事务状态调用setRollbackOnly
,也可以引发运行时异常
注意:如果使用异常,它们可能会很昂贵,因此最好创建一个自定义异常类型,例如
GroupUpdateException
,并覆盖fillInStackTrace
,以不填充堆栈跟踪,从而降低异常的成本。请参阅我倾向于接受您的第二个建议(使用异常)。但是,问题中的案例不起作用有什么原因吗?我想,这就是解决问题的方法。感谢您的回答。可能是您的附加检查执行的查询导致更新自动刷新,因此查询是一致的,这就是为什么使用事务很重要