0

私は Grails 2.4.2 を使用しており、多くのInvoiceRecipientを持つクラスContractを持っています。InvoiceRecipients クラスには、 invoice -original の「O」と送り状のコピーの「C」の2 つの可能な値を持つ、 invoiceType属性があります。ご想像のとおり、1 つの契約の InvoiceRecipients には、タイプが「O」の1 つのレコードのみが許可されます。

次のスニペットのように実装しようとすると、VM で StackOverflow が発生します。

私が試した別のアプローチは、契約の受信者配列を反復処理して、invoiceType 'O' のレコードをカウントするサービス メソッドでした。 ->コントローラーの invoiceRecipients リレーション。

最後の両方のケースで、Hibernate は現在の InvoiceRecipient レコードの更新ステートメントを生成し、これを検証しようとします。また、現在の InvoiceRecipient の検証が失敗し、インスタンスのエラー オブジェクトにデータを入力した場合でも、レコードは既に更新されています (制約はクラスにコーディングされておらず、「保存」でエラーをスローしないため、問題はありません)。データベースに論理的に間違ったレコードがあります。

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 に答える