12

我有一个父域类,它有hasMany另一个域类。父域类和子域类都有lastUpdateddateCreated字段。我的问题是,当我更新子域类时,我需要父域类来反映该更改并更新其lastUpdated字段。

Grails 提供的父子节点之间是否有任何映射或其他配置可以实现此功能?

更新

我在子域类中添加了以下几行:

def beforeUpdate = {
    parent.lastUpdated = new Date()
}

我还必须在控制器中确保当我更新一个孩子时,我还必须保存父级以保留新lastUpdated字段。这似乎工作正常,但我仍然想知道是否有映射或类似的东西可以做到这一点。

4

3 回答 3

2

我感觉你建议的实现会有问题。您正在通过手动parent设置日期来更新,这可能会导致 grails在对其进行脏检查后再次更新。如果是这种情况,您实际上会得到一个 lastUpdated 时间,该时间发生在您最初设置的日期之后。在您的测试中,这可能只有几(毫秒)秒,但您不能保证。lastUpdatedlastUpdated

不仅如此,您的实现也更难维护,因为您增加了 Parent 和 Child 的耦合。

我可以建议另一种实现吗?lastUpdated 字段应该代表特定域对象的更新时间。您要查找的日期并不完全相同,因此我不会尝试以“错误”的方式使用现有约定。听起来您希望父对象的日期是“最后一次修改子对象”。

请改用公式。

为此,您可以使用公式。使用公式,您无需直接修改父对象即可获得您想要的结果,并且您仍然可以使用动态查找器和其他 Grails 糖。

class Parent {
    ...
    Date lastChildUpdated

    static hasMany = [ children: Child ]

    static mapping = {
        ...
        lastChildUpdated formula: '(SELECT max(c.last_updated) FROM child c WHERE c.parent_id = id)'
    }
}

每当您从数据库中读取对象时,GORM 都会加载公式的值。现在,每当您保存子项时,父项将获得该属性的准确值,而无需触摸父项。

于 2012-07-17T21:37:34.107 回答
1

我用了一个黑客。我在父域类和方法中添加了一个Long updateTrigger字段:touch

class Parent {
    Long updateTrigger

    static mapping = {
        autoTimestamp true
    }

    static constraints = {
        updateTrigger(nullable:true)
    }

    public touch() {
        if (updateTrigger == null) updateTrigger = 0
        updateTrigger++
        this
    }

控制器的更新/保存操作中,我只是调用:

child_instance.save() // save the child
child_instance.parent.touch().save() // updates parent's time stamp

这将增加updateTrigger值,并且由于映射中的设置,save()将自动更新lastUpdated字段。设置为可为空,这样它就不会使任何现有的数据库表无效,因此可以随时添加到任何域类。autoTimestamptrueupdatedTrigger

于 2013-11-27T21:00:09.483 回答
0

在我的一个项目中,域就像。一个程序有很多 AdvertisingMaterial,我们有 AdvertisingMaterial、FlashAd、ImageAd 等的子类。用户希望能够过滤具有 flashAds、imageAds 等的程序。现在我需要根据我们拥有的类属性进行过滤在数据库表中(当表 tablePerHierarchy 为真时)。所以我在我的域类中做了一些改变来获得这个属性。

class AdvertisingMaterial {
        String className

        static constraints = {
                className(nullable: true)
        }

       static mapping = {
               className formula: 'CLASS'
       }
} 

现在我也可以在我的动态查找器和条件查询中使用这个 className 字段。所以我可以做类似的事情

List<AdvertisingMaterial>adMaterials=AdvertisingMaterial.findAllByClassName("com.project.FlashAd")

static mapping = {
               fullName formula: "CONCAT(FIRST_NAME,'  ',LAST_NAME)"
               totalAmount formula: "SUM(AMOUNT)"
}
于 2013-01-29T08:57:31.630 回答