如何添加验证以限制正在创建的行数

安东尼

我有一个Grails域类。我想添加一个验证,以便当应用程序在TEST环境中运行时,域类的记录不能超过100条。

我想不出添加这种类型验证的最佳方法。我正在使用Grails 2.5.3。

到目前为止,这就是我所拥有的。

class MyDomain {

String test

static constraints = {
   test blank: false, nullable: false
   id blank: false, validator: {value, command -> 
      if (Environment.current == Environment.TEST) {
          //do validation for not allowing more than 100 records
      }
   }
}

如何添加此验证?

沙尚克·阿格劳瓦尔(Shashank Agrawal)

单个域的解决方案

@Joshua回答的还好,但是还有其他几种方法。其中之一是:

class MyDomain {

    String test

    void beforeInsert() {
        if (Environment.current == Environment.TEST) {
            MyDomain.withNewSession {
                if (MyDomain.count() == 100) {
                    throw new Exception("Not allowing more than 100 records")
                }
            }
        }
    }

    static constraints = {
        test blank: false
    }
}

另外,请注意两件事:

  1. blank: falseid,因为它没有使用领域是不是一个字符串,因为blank限制适用于字符串
  2. 之所以nullable: false没有用,是因为nullable约束的默认值为false

跨域TL; DR的通用解决方案

如果您希望跨多个域执行此操作,则不建议复制相同的代码,因为您的代码不会是DRY。为此,您可以注册一个自定义事件侦听器:

首先在中定义Java批注src/groovy

import java.lang.annotation.Documented
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target

@Documented
@Target([ElementType.TYPE, ElementType.FIELD])
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitRowsFoo {

    int value() default 100
}

现在定义另一个Groovy类:

import grails.util.Environment
import org.grails.datastore.mapping.engine.event.PreInsertEvent
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener

class PreInsertEventListener extends AbstractPersistenceEventListener {

    PreUpdateEventListener(final Datastore datastore) {
        super(datastore)
    }

    @Override
    protected void onPersistenceEvent(AbstractPersistenceEvent event) {
        // Instance of domain which is being created
        Object domainInstance = event.entityObject

        if (Environment.current == Environment.TEST) {
            if (domainInstance.class.isAnnotationPresent(LimitRowsFoo.class)) {
                // Just using any domain reference here
                MyDomain.withNewTransaction {
                    int maxRows = domainInstance.class.getAnnotation(LimitRowsFoo.class).value()
                    if (domainInstance.class.count() == maxRows) {
                        event.cancel()
                    }
                }
            }
        }
    }

    @Override
    boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        // Only allow PreInsert event to be listened
        eventType.name == PreInsertEvent.class.name
    }
}

现在在Bootstrap.groovy

application.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore ->
        applicationContext.addApplicationListener new PreInsertEventListener(datastore)
    }

现在,在您的域中,您需要做的就是这些:

@LimitRowsFoo
class MyDomain {

    String test

    static constraints = {
        test blank: false
    }
}

@LimitRowsFoo(value = 200)   // to limit records to 200
class MyAnotherDomain {

    String name
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章