在自己的域上进行 Grails 验证

Grails validation over own domain

我正在使用 Grails 2.4.2 并且有一个 class Contract,其中有许多 InvoiceRecipient 的 。 InvoiceRecipients class 有一个属性 invoiceType,它有 2 个可能的值,'O' 代表发票原件,'C' 用于发票副本。正如您所想象的,一份合同的 InvoiceRecipients 只允许一条类型为 'O' 的记录。

如果我尝试按照以下代码片段实现它,VM 会遇到 Whosebug。

我尝试的另一种方法是一种服务方法,它遍历合同的接收者数组以计算发票类型 'O' 的记录,或者我尝试通过 [=36= 进行 select 计数]() 来确定控制器中 contract->invoiceRecipients 关系中 'O' 的数量。

在后两种情况下,Hibernate 都会为我当前的 InvoiceRecipient 记录生成一个更新语句,我会尝试对其进行验证。即使当前 InvoiceRecipient 的验证失败并且我填充了实例的错误对象,记录也已经更新(没有问题,因为约束没有编码到 class 并且 "save".) 我在数据库中有逻辑错误的记录。

class Contract implements Serializable {
    ...
    static hasMany = [recipients: InvoiceRecipient]
    ...
}

class InvoiceRecipient implements Serializable {
    static belongsTo = [contract: Contract]
    ...
    String invoiceType
    ...

    static constraints = {
        invoiceType nullable: false, maxLength: 1, inList: ['O', 'C'], validator: { val, obj ->
        /* => This generates a Whosebug
        if (InvoiceRecipient.countByContractAndInvoiceType(obj.contract, 'O') > 1)
            return "invoiceRecipient.original.max.exceed"
        */
    }
}

我可能会使用这样的东西:

validator: { val, obj ->
if (obj.recipients.findAll{invoiceType == 'O'}.size() > 1)
        return "invoiceRecipient.original.max.exceed"

这样您应该能够防止 Hibernate 尝试刷新脏对象并在该过程中重新验证该对象。