0

I'm using Grails 2.4.2 and have a class Contract which has many InvoiceRecipient's. The InvoiceRecipients class has an attribute invoiceType which has 2 possible values, 'O' for the invoice-original and 'C' for an invoice-copy. As you could imagine, only one record with type 'O' is allowed for the InvoiceRecipients for one contract.

If I try to implement it as in the following snipplet, the VM runs into a StackOverflow.

Another approach I tried was a service method which iterates through the recipients array of the contract to count the records with invoiceType 'O' or I tried to do a select count through InvoiceRecipient.countByContractAndInvoiceType() to determine the number of 'O's in the contract->invoiceRecipients relation in the controller.

In both last cases, Hibernate generates an update statement for my current InvoiceRecipient record, which I try to validate. And even if the validation of the current InvoiceRecipient fails and I populate the errors-object of the instance, the record is already updated (without problems, because the constraint is not coded into the class and throws no error in "save".) And I have the logical-wrong records in the database.

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"
        */
    }
}
4

1 回答 1

1

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

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

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

于 2015-06-04T10:59:05.747 回答