通过自己的域进行Grails验证

时间:2015-06-04 10:51:19

标签: hibernate grails grails-domain-class grails-controller grails-validation

我使用的是Grails 2.4.2,并且有一个合同,其中有很多 InvoiceRecipient&#39>。。 InvoiceRecipients类具有属性 invoiceType ,其中包含两个可能的值,' O' 用于发票原件和' C&# 39; 用于发票复印件。您可以想象,对于一份合同,InvoiceRecipients只允许使用类型为' O' 的一条记录。

如果我尝试按照以下snipplet实现它,则VM会运行到StackOverflow。

我尝试的另一种方法是一种服务方法,它迭代合同的收件人数组,用invoiceType' O'来计算记录。或者我尝试通过InvoiceRecipient.countByContractAndInvoiceType()进行选择计数,以确定控制器中合同 - > invoiceDecipients关系中的'

在最后两种情况下,Hibernate为我当前的InvoiceRecipient记录生成一个更新语句,我尝试对其进行验证。即使当前InvoiceRecipient的验证失败并且我填充了实例的errors-object,记录也已经更新(没有问题,因为约束没有编码到类中并且在&#34中没有引发错误;保存&# 34;。)我在数据库中有逻辑错误的记录。

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 StackOverflow
        if (InvoiceRecipient.countByContractAndInvoiceType(obj.contract, 'O') > 1)
            return "invoiceRecipient.original.max.exceed"
        */
    }
}

1 个答案:

答案 0 :(得分:1)

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

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

这样你就可以防止Hibernate尝试刷新脏对象,并在此过程中重新验证这个对象。