5

我有一个问题,我的域类有两个潜在的互斥外部键,一个序列号或一个旧的查找值。

由于我不确定任何给定条目将具有哪一个,因此我将它们设为可空并添加了自定义验证以确保我只有一个值。

package myproject 

class Sample {

    String information
    String legacyLookup
    String serialNumber

    static constraints = {
        information(nullable: true)
        legacyLookup(nullable: true)
        serialNumber(nullable: true)

        legacyLookup validator: {
            return ((serialNumber != null && legacyLookup == null) || (serialNumber == null && legacyLookup != null))
        }

        serialNumber validator: {
            return ((serialNumber != null && legacyLookup == null) || (serialNumber == null && legacyLookup != null))
        }
    }
}

我创建了默认的 CRUD 屏幕并尝试为此域类创建一个条目

information: Blah Blah
serialNumber: 
legacyLookup: BLAHINDEX123

这在验证器中死亡,并显示以下消息:

No such property: serialNumber for class: myproject.Sample

我错过了什么?

4

3 回答 3

9

无需多次将每个属性都放在其中;实际上,您只需要其中一个实际受约束。此外,您不能只通过名称直接引用属性。有些对象传递给约束闭包,用于获取值(请参阅文档)。可能我发现的最简单的方法如下:

class Sample {
    String information
    String legacyLookup
    String serialNumber

    static constraints = {
        information(nullable: true)
        legacyLookup(validator: {val, obj->
            if( (!val && !obj.serialNumber) || (val && obj.serialNumber) ) {
                return 'must.be.one'
            }
        })
    }
}

然后在 messages.properties 文件中有一个条目,如下所示:

must.be.one=Please enter either a serial number or a legacy id - not both

或者您可以为每个条件提供单独的消息 - 两者都输入,或者两者都是空白的,如下所示:

legacyLookup(validator: {val, obj->
    if(!val && !obj.serialNumber) {
         return 'must.be.one'
    }
    if(val && obj.serialNumber) { 
         return 'only.one'
    }
})

然后在 message.properties 中有两条消息:

only.one=Don't fill out both
must.be.one=Fill out at least one...

如果没有错误,您不需要从约束中返回任何内容......

于 2012-07-14T06:20:13.833 回答
0

如果您想确保您拥有“一个且只有一个值”,另一种选择是创建一个名为的通用字段,该字段serialNumberLegacyLookup将同时代表serialNumberlegacyLookup字段。然后,您可以向名为的域类添加一个布尔字段,legacyLookup默认为false. 然后,您可以通过验证器运行该值并对其进行解析以查看它是“序列号”还是“旧版查找”值。如果该值原来是“旧版查找”值,那么您可以将legacyLookup布尔值设置为true. 我认为从 UI 的角度来看,这种方法不会令人困惑(用户只需填写一个字段,而不是两个条件字段)。

于 2012-07-14T04:32:30.090 回答
-1

我遇到了同样的情况,我找到的解决方案是创建一个 getter 方法并为其添加一个约束。

package myproject 

class Sample {

    String information
    String legacyLookup
    String serialNumber

    def getTarget(){
        if (legacyLookup && !serialNumber) {
            return legacyLookup
        } else if (!legacyLookup && serialNumber) {
            return serialNumber
        } else {
            return null
        }
    }

    static constraints = {
        information(nullable: true)
        legacyLookup(nullable: true)
        serialNumber(nullable: true)
        target(nullable: false)
    }
}
于 2017-09-22T19:00:19.183 回答