Grails自定义验证 - 验证内部查询 - 更新时会发生什么? [英] Grails Custom Validation - Query inside validation check - What happens while updating?

查看:83
本文介绍了Grails自定义验证 - 验证内部查询 - 更新时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 验证器:{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)

$ b admin.addToAuthorities(ADMIN)。save(flush:true)
$ b



Grails正在运行验证,即使在更新时也是如此,因为电子邮件存在验证失败。如果我这样做,这有什么不同?

email {unique:true}



Grails说我不能编写一个自定义验证器来检查唯一性。

解决方案

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



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

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


请参阅 UniqueConstraint 作为一个例子来说明这一点。


I have a custom validator like -

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;
      }

...

So basically, I need some validation based on some condition and in my validation I need to execute a query.

But, now if I do -

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


admin.save(flush:true)


admin.addToAuthorities("ADMIN").save(flush:true)

It fails.

Grails is running the validation, even on update and since email exists validation fails. How is this different if I do

email {unique:true}

Is Grails saying that I cannot write a custom validator which checks uniqueness.

解决方案

Not sure if this is your issue or not, but when I tried to create a validation like this (ie. one that does queries against the database), I would get a StackOverflowError. The reason is that, when you run a query (like findByEmail), Hibernate will try to flush the session, which will cause it to validate all transient objects, which in turn calls your custom validator again, resulting in infinite recursion.

The trick to prevent this is to set the flush mode of the session to "manual" for a short time while running the queries. This prevents Hibernate from trying to flush the session before running the queries. The side-effect is that your query won't return entities you created in the current session but haven't been persisted (flushed) back to the database yet.

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);
    }
}

See UniqueConstraint for an example of how this is done.

这篇关于Grails自定义验证 - 验证内部查询 - 更新时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆