1

親関係の更新を子に伝達するネストされたドメイン クラスに関する内部要件があります。コード例はそれを明確にするかもしれません:

class Milestone {
    static belongsTo = [project:Project]
    static hasMany = [goals:OrgGoals, children:Milestone]
    String name
    Date start
    Date estimatedEnd
    Date achievedEnd
    ...
}

親マイルストーンの EstimatedEnd が更新されると、子の見積もりが同じ量だけ自動的に更新されるようにします。GORM の beforeUpdate() フックは、これを行う論理的な場所のようです。

生活を楽にするために、いくつかの単純な Date 演算を使用したいので、Milestone クラスに次のメソッドを追加しました。

def beforeUpdate()
    {
        // check if an actual change has been made and the estimated end has been changed
        if(this.isDirty() && this.getDirtyPropertyNames().contains("estimatedEnd"))
        {
            updateChildEstimates(this.estimatedEnd,this.getPersistentValue("estimatedEnd"))
        }
    }

private void updateChildEstimates(Date newEstimate, Date original)
    {
        def difference = newEstimate - original
        if(difference > 0)
        {
            children.each{ it.estimatedEnd+= difference }
        }
    }

コンパイル エラーはありません。しかし、次の統合テストを実行すると:

void testCascadingUpdate() {
        def milestone1 = new Milestone(name:'test Parent milestone',
            estimatedEnd: new Date()+ 10,
        )
        def milestone2 = new Milestone(name:'test child milestone',
            estimatedEnd: new Date()+ 20,
        )
        milestone1.addToChildren(milestone2)
        milestone1.save()
        milestone1.estimatedEnd += 10
        milestone1.save()
        assert milestone1.estimatedEnd != milestone2.estimatedEnd
        assert milestone2.estimatedEnd == (milestone1.estimatedEnd + 10)
    }

私は得る:

Unit Test Results.

    Designed for use with JUnit and Ant.
All Failures
Class   Name    Status  Type    Time(s)
MilestoneIntegrationTests   testCascadingUpdate Failure Assertion failed: assert milestone2.estimatedEnd == (milestone1.estimatedEnd + 10) | | | | | | | | | | | Mon Jun 06 22:11:19 MST 2011 | | | | Fri May 27 22:11:19 MST 2011 | | | test Parent milestone | | false | Fri May 27 22:11:19 MST 2011 test child milestone

junit.framework.AssertionFailedError: Assertion failed: 

assert milestone2.estimatedEnd == (milestone1.estimatedEnd + 10)
       |          |            |   |          |            |

       |          |            |   |          |            Mon Jun 06 22:11:19 MST 2011
       |          |            |   |          Fri May 27 22:11:19 MST 2011
       |          |            |   test Parent milestone

       |          |            false
       |          Fri May 27 22:11:19 MST 2011
       test child milestone

    at testCascadingUpdate(MilestoneIntegrationTests.groovy:43)

    0.295

これは、 beforeUpdate が起動しておらず、私が望むことをしていないことを示唆しています。何か案は?

4

1 に答える 1

5

解決策があります。

1)milestone1 の EstimatedEnd を更新した後、2 回目の save 呼び出しで save(flush:true) を呼び出します。これにより、 beforeUpdate() がすぐに起動されます。

2) #1 を実行した後でも、わずかに異なる 2 つの日付を比較しているため、アサーションは失敗し続けます (各マイルストーン コンストラクター内で個別の Date オブジェクトを使用するため、2 番目の日付は最初の日付よりもわずかに遅い/大きいです)。同じ日付インスタンスを使用しました。

Date date = new Date() 
def milestone1 = new Milestone(name:'test Parent milestone',
            estimatedEnd: date + 10)
def milestone2 = new Milestone(name:'test child milestone',
            estimatedEnd: date + 20,
        )

その後、アサーションは成功します。わずかに異なる日付を比較する最良の方法に関して、次に何をすべきかはあなたにお任せしますが、ミリ秒単位の精度の違いを許容する必要があるかもしれません。

それが役立つことを願って、

ヨルダン

于 2011-05-08T17:29:18.743 に答える