Grails自定义验证-验证检查内部查询-更新时会发生什么?

Grails自定义验证-验证检查内部查询-更新时会发生什么?,grails,Grails,我有一个自定义验证器,如- validator: { userEmail, userAccount -> if (userAccount.authenticationChannel == "ABC") { boolean valid = true; UserAccount.withNewSession { if (UserAccount.findByEmail(userEmail)){ valid = false;

我有一个自定义验证器,如-

validator: { userEmail, userAccount ->

   if (userAccount.authenticationChannel == "ABC") {
      boolean valid = true;
      UserAccount.withNewSession {
      if (UserAccount.findByEmail(userEmail)){
         valid = false;
      }
      else if (UserAccount.findByName(userEmail)) {
         valid = false;
      }

因此,基本上,我需要基于某些条件进行一些验证,在验证过程中,我需要执行一个查询

但是,现在如果我这样做了-

def admin = new UserAccount(firstname:'Admin',email:'admin@example.com')


admin.save(flush:true)


admin.addToAuthorities("ADMIN").save(flush:true)
它失败了

Grails正在运行验证,即使是在更新时,而且由于电子邮件存在,验证也会失败。如果我这样做,这有什么不同

email{unique:true}


Grails是说我无法编写检查唯一性的自定义验证器。

另一种方法可能是在save方法中进行检查

def save = {
  ..
  if (some_checks_succeed(userEmail, userAccount)) {
    admin.save(flush: true)
  }
  ..
}

def some_checks_succeed = { String userEmail, String userAccount ->
  boolean valid = true;
  if (userAccount.authenticationChannel == "ABC") {
    UserAccount.withNewSession {
    if (UserAccount.findByEmail(userEmail)) {
     valid = false;
    } else if (UserAccount.findByName(userEmail)) {
     valid = false;
    }

    ..
  }

  return valid
}

可能需要进行一些修改,但上面的代码为您提供了一个示例,谢谢。我可以让它工作。admin.save()在插入和更新时都调用验证。我处理了这两种情况(插入和更新),并能够使其正常工作


谢谢

我不确定这是否是您的问题,但当我尝试创建这样的验证(即,对数据库进行查询的验证)时,我会得到一个StackOverflower错误。原因是,当您运行查询(如
findByEmail
)时,Hibernate将尝试刷新会话,这将导致它验证所有临时对象,然后再次调用您的自定义验证器,从而导致无限递归

防止这种情况的诀窍是在运行查询时将会话的刷新模式设置为“手动”一小段时间。这可以防止Hibernate在运行查询之前尝试刷新会话。副作用是,查询不会返回您在当前会话中创建的实体,但尚未持久化(刷新)回数据库

UserAccount.withNewSession { session ->
    session.flushMode = FlushMode.MANUAL
    try {
        if (UserAccount.findByEmail(userEmail)){
            valid = false;
        }
        else if (UserAccount.findByName(userEmail)) {
            valid = false;
        }
    }
    finally {
        session.setFlushMode(FlushMode.AUTO);
    }
}

有关如何执行此操作的示例,请参阅。

>此操作失败。如果您提供任何异常或失败stacktrace,将更容易帮助您。正如下面Olexandr所述,stacktrace将非常有用。“它失败了”不是很清楚。嗨,你能提供一个到你的UniqueConstraint示例的更新链接吗?不幸的是,那一个给出的是404。更新。在github上再也找不到原始文件。与RockyJ有相同的问题。他们应该在验证器的文档中提到这一点。