Grails,我如何得到一个不能保存的对象

时间:2010-05-25 21:00:42

标签: java grails groovy gorm

我不熟悉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语句而未击中其他语句,所以它永远不会遇到保存的调用( )方法,但它仍然保存。

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

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

5 个答案:

答案 0 :(得分:10)

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

这是由失败的验证器自动完成的,这就是为什么你不必为验证失败而这样做。

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

答案 1 :(得分:6)

使用get()方法以读写模式检索数据,所以如果你改变任何东西它将是persist.Use read()方法可以以只读模式检索数据,所以如果你改变任何东西,那么需要使用save ()方法。这将解决您的问题。

看看这个http://grails.org/doc/latest/guide/GORM.html#basicCRUD

答案 2 :(得分:2)

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

请参阅Grails documentation about read

答案 3 :(得分:0)

你正在做的闪回与回滚交易无关。 如果发生错误抛出RuntimeException,它会将您的更改回滚到数据库。

答案 4 :(得分:0)

经过R& D,我发现我们需要清除整个会话,如:

session.clear()

根据documentation

  

彻底清除会话。退出所有已加载的实例并取消   所有待处理的保存,更新和删除。不要关闭打开的迭代器   或ScrollableResults的实例。

我们需要正确清理hibernate会话。结果会话返回到可用状态,并且将来使用它不会受到先前错误的影响。