首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Grails钩入GORM beforeUpdate()

Grails钩入GORM beforeUpdate()
EN

Stack Overflow用户
提问于 2011-05-08 13:35:29
回答 1查看 5.5K关注 0票数 1

对于嵌套的域类,我有一个内部需求,我希望将父关系的更新传播给子关系。代码示例可以清楚地说明这一点:

代码语言:javascript
复制
class Milestone {
    static belongsTo = [project:Project]
    static hasMany = [goals:OrgGoals, children:Milestone]
    String name
    Date start
    Date estimatedEnd
    Date achievedEnd
    ...
}

当父里程碑的estimatedEnd更新时,我希望子里程碑的估计值自动更新相同的量。GORM's beforeUpdate() hook似乎是做这件事的合乎逻辑的地方:

为了方便起见,我想使用一些simple Date arithmetic,所以我将以下方法添加到里程碑类中:

代码语言:javascript
复制
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 }
        }
    }

没有编译错误。但是当我运行以下集成测试时:

代码语言:javascript
复制
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)
    }

我得到了:

代码语言:javascript
复制
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不会触发并执行我想要的操作。有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-05-09 01:29:19

我有一个解决方案给你。

1)在更新Milestone1的estimatedEnd之后,在第二次保存调用时调用save(flush:true)。这将强制beforeUpdate()立即触发。

2)即使在您执行了#1之后,您的断言也将继续失败,因为您正在比较两个略有不同的日期(您在每个里程碑构造函数中使用单独的Date对象,因此第二个日期比第一个日期稍晚/晚一些)。如果您使用相同的date实例,例如

代码语言:javascript
复制
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,
        )

那么断言就会成功。我将把比较略有不同的日期的最佳方式留给您下一步做什么,但您可能不得不容忍毫秒级的精度差异。

希望这能有所帮助,

乔丹

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5925807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档