【问题标题】:Grails , how do I get an object NOT to saveGrails,我如何让一个对象不保存
【发布时间】:2011-02-23 21:49:03
【问题描述】:

我是 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() 方法的文档,您可以在上面的代码中看到该方法。所以我添加了这个,但仍然无济于事。我什至尝试使用丢弃,然后再次从数据库重新加载客户端对象,但仍然没有骰子。

这很令人沮丧,如果能得到任何帮助,我将不胜感激,因为我认为这肯定不是一个复杂的要求!

【问题讨论】:

  • client.discard() 应该是这样做的方法,你能在集成测试中重现这个问题吗?您使用的是什么版本的 Grails?
  • 我刚刚尝试了对代码的集成测试,奇怪的是它似乎表现得如我所愿,但是当我通过网络正常进行时,我又遇到了同样的问题。我会发布我的测试代码,但我不知道如何在这里做,它告诉我它的字符太多
  • 你应该接受下面的答案!

标签: java grails groovy grails-orm


【解决方案1】:

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

这是由失败的验证器自动完成的,这就是为什么您不必为验证失败执行此操作。

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

【讨论】:

  • 是的,但这就是让我困惑的地方,我正在使用丢弃,这正在集成测试中,但不在网络上
  • 请记住,集成测试最后会回滚您的事务。在网络上,您的事务最终将提交。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    使用read 方法检索处于只读状态的指定id 的域类实例。

    请参阅Grails documentation about read

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 这对我有用,虽然我不明白为什么如果你使用 get,丢弃不起作用,无论如何谢谢
      【解决方案5】:

      经过研发,我发现我们需要清除整个会话,例如:

      session.clear()
      

      根据documentation

      完全清除会话。驱逐所有加载的实例并取消 所有待处理的保存、更新和删除。不要关闭打开的迭代器 或 ScrollableResults 的实例。

      我们需要正确清理休眠会话。结果会话返回到可用状态,并且为了将来的使用,它不会受到早期错误的影响。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-06
        • 1970-01-01
        • 2014-06-04
        相关资源
        最近更新 更多