验证域类的实例是唯一的

Posted

技术标签:

【中文标题】验证域类的实例是唯一的【英文标题】:Validate instance of domain class is unique 【发布时间】:2013-08-19 13:28:58 【问题描述】:

我有一个 Grails 应用程序,其中包含一堆域类,其中一些具有许多字段,其中一些与所讨论的域类具有 hasMany 关系。对于这个特定的应用程序,我只有一个“约束”,即每个域类的每个实例都必须是唯一的。我不在乎一个任意字段是否在同一个域类的多个实例中具有相同的值,只要每个实例都由该域类中某个其他字段的值唯一。所以基本上我希望验证发生在域类实例级别而不是域类字段级别。现在我正在这样做,方法是使用非常时髦的 @EqualsAndHashCode 注释来生成我的 equalshashCode 方法,然后在域类的某个任意字段上的自定义验证器中调用 equals

两个问题:

    是否有更有效的方法来验证域类是否唯一? 如果不是,那么有没有一种方法可以在域类实例本身上调用我的自定义验证器代码,而不是通过域类实例的某个字段?
@groovy.transform.EqualsAndHashCode 类 MyDomainClass 串一些 整数任意 布尔字段 静态约束 = // 我选择验证的字段无关紧要,我只需要在**某处**运行验证代码 任意验证器: val, obj -> 返回 !MyDomainClass.getAll().contains(obj)

我还应该补充一点,我正在寻找一种通用的(希望是有效的)方法来做到这一点。我意识到调用getAll() 效率非常低,而是调用find 的一些变体或对每个域类的确切字段执行HQL 查询会更有效......它只需要更长的时间来编写!

示例

    assert MyDomainClass.getAll().isEmpty() // true

    def myDomainClass1 = new MyDomainClass( some: "foo", arbitrary: 1, field: true)
    assert MyDomainClass.getAll().contains(myDomainClass1); // false
    myDomainClass1.save(flush:true)

    def myDomainClass2 = new MyDomainClass( some: "bar", arbitrary: 1, field: true)
    assert MyDomainClass.getAll().contains(myDomainClass2); // false.  Even though this has the same `arbitrary` value as myDomianClass1, it has a different `some` value which makes it unique.
    myDomainClass2.save(flush:true)

    def myDomainClass3 = new MyDomainClass( some: "foo", arbitrary: 1, field: false)
    assert MyDomainClass.getAll().contains(myDomainClass3); // false.  Even though this has the same `some` value as myDomainClass1 and the same `arbitrary` value as myDomainClass1 and myDomainClass2, it has a different `field` value which makes it unique.
    myDomainClass3.save(flush:true)

【问题讨论】:

很难理解你在问什么。您想知道域类是否是唯一的,但不是在字段级别。除了域的字段之外,您还如何确定它是否是唯一的?你能不说arbitrary unique: true吗???在这种情况下,提供您正在使用的实际示例会有所帮助。 @JamesKleeh 如果我说arbitrary unique: true,则意味着该MyDomainClass 的任何其他实例中的任何其他arbitrary 字段都不会具有相同的值。那不是我想要的。我希望MyDomainClass 的其他实例能够具有完全相同的arbitrary 值,只要其他字段的值使域类的实例唯一。我将添加一个更好的例子来说明这一点。 那么你需要添加一个跨越所有字段的唯一约束。 some unique: ['arbitrary', 'field'] @JamesKleeh 如果我使用多列unique(我认为这就是您的建议)我将不得不为MyDomainClass 中的每个字段执行此操作。示例:some(unique:['arbitrary', 'field'] 然后arbitrary(unique: ['some', 'field']) 然后field(unique:['some', 'arbitrary'])。我很确定这会得到我想要的(而且它肯定比我现在做的更有效),但如果可能的话,我想要一个更通用的解决方案。 您只需将约束放在一个字段上。我在上面展示的示例将确保 some、任意和 field 将是唯一键。你的所有三个例子都做同样的事情,你把它放在什么顺序和字段上是......任意的:) 【参考方案1】:

这将确保域中 3 个字段的组合是唯一的。这也确保了约束是在数据库级别,而不仅仅是应用程序级别。

class MyDomainClass 
    String some
    int arbitrary
    boolean field
    static constraints = 
        some(unique: ['arbitrary', 'field'])
    

【讨论】:

我会试试这个。我测试过一次(过去在不同的应用程序上),我记得它的工作方式不同。希望我错了:) 这似乎像您想象的那样工作。我猜我让它比实际更难:/

以上是关于验证域类的实例是唯一的的主要内容,如果未能解决你的问题,请参考以下文章

Grails:将自定义约束应用于域类的所有字段

grails 和 spring security acl:仅显示域类的一些实例

日期验证的 Grails 最小约束

Grails 域标准验证器:我应该测试还是不测试?

Grails - 从自定义验证器闭包调用内置约束

我如何验证给定类的每个实例都被应用程序终止破坏了?