Java Grails,如何获取不保存的对象

Java Grails,如何获取不保存的对象,java,grails,groovy,gorm,Java,Grails,Groovy,Gorm,我是grails新手,正在尝试创建一个表单,允许用户更改与我正在创建的站点的帐户关联的电子邮件地址 它要求用户提供其当前密码,以及他们想要使用的新电子邮件地址。 如果用户输入了错误的密码或无效的电子邮件地址,则应使用相应的错误消息拒绝这些密码或地址 现在,电子邮件验证可以通过grails中的约束来完成,但是密码更改必须与当前密码匹配。我已将此检查作为服务类上的方法实现 见下面的代码: def saveEmail = { def client = ClientUser.get(sessio

我是grails新手,正在尝试创建一个表单,允许用户更改与我正在创建的站点的帐户关联的电子邮件地址

它要求用户提供其当前密码,以及他们想要使用的新电子邮件地址。 如果用户输入了错误的密码或无效的电子邮件地址,则应使用相应的错误消息拒绝这些密码或地址

现在,电子邮件验证可以通过grails中的约束来完成,但是密码更改必须与当前密码匹配。我已将此检查作为服务类上的方法实现

见下面的代码:

def saveEmail =
{
    def client = ClientUser.get(session.clientUserID)
    client.email = params.email
    if(clientUserService.checkPassword(session.clientUserID , params.password) ==false)
    {
        flash.message = "Incorrect Password"
        client.discard()
        redirect(action:'changeEmail')
    }    
    else if(!client.validate())
    {
         flash.message = "Invalid Email Address"
         redirect(action:'changeEmail')
    }
    else
    {
        client.save();
        session.clientUserID = null;
        flash.message = "Your email address has been changed, please login again"
        redirect(controller: 'clientLogin' , action:'index')
    }
}
现在我注意到奇怪的是,如果我输入了一封无效的电子邮件,那么它不会保存更改(如预期的那样),但是如果我输入了错误的密码和有效的电子邮件,那么它会保存更改,甚至将更改写回数据库,即使它会给出正确的“无效密码”错误消息

我很困惑,所以在所有if/else if/else块中设置断点,发现它按预期命中了第一个if语句,而没有命中其他语句,因此它永远不会调用save()方法,但它还是被保存了

经过一点研究,我得到了关于discard()方法的跨文档,您可以在上面的代码中看到它的用法。所以我加了这个,但还是没用。我甚至尝试使用discard,然后再次从DB重新加载客户机对象,但仍然没有骰子


这是非常令人沮丧的,我将感谢任何帮助,因为我认为这肯定不是一个复杂的要求

Grails在web请求结束时关闭Hibernate会话,这将清除已更改的对象。该对象已连接到您的Hibernate会话,因为您通过Hibernate(
get()
)获得了它。如果要避免刷新更改,需要使用
discard()

这是由一个失败的验证器自动完成的,这就是为什么您不必为验证失败而这样做的原因


但是,您可以通过将此逻辑移动到
ClientUser
字段之一上的自定义验证器来简化代码,该字段将在失败时自动丢弃该对象,或者通过使用Grails命令对象来简化代码,该对象也可以封装验证逻辑。然后,您只需检查命令对象上的错误。

您只是在执行flash,这与回滚事务无关。
如果发生错误,抛出RuntimeException,它将回滚对数据库的更改。

使用
read
方法,以只读状态检索指定id的域类实例

请参阅。

使用get()方法在读写模式下检索数据,因此,如果您更改任何内容,它将保持不变。使用可以在只读模式下检索数据的read()方法,因此如果您更改任何内容,则需要使用save()方法。这将解决您的问题


看看这个

在研发之后,我发现我们需要清理整个会话,如:

session.clear()
根据报告:

完全清除会话。逐出所有加载的实例并取消 所有挂起的保存、更新和删除。不要关闭打开的迭代器 或可滚动结果的实例


我们需要正确地清理hibernate会话。因此,会话将返回到可用状态,为便于将来使用,它不会受到早期错误的影响。

client.discard()应该是这样做的,您能在集成测试中重现该问题吗?您使用的是什么版本的Grails?我刚刚对代码进行了一次集成测试,奇怪的是,它的行为似乎符合我的要求,但当我正常通过web进行测试时,我又遇到了同样的问题。我会发布我的测试代码,但我不知道如何在这里做到这一点,它告诉我,这是太多的chars你应该接受下面的答案!是的,但这正是困扰我的,我正在使用discard,这是在集成测试上工作,但不是在Web上。记住,集成测试会在最后回滚您的事务。在web上,您的事务最终将提交。这对我来说很有效,但我不明白如果您使用get,为什么放弃不起作用,无论如何,谢谢