更新Grails中父域类中的“lastUpdated”字段

时间:2012-06-26 16:01:02

标签: grails gorm grails-domain-class

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

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

更新

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

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

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

3 个答案:

答案 0 :(得分:2)

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

不仅如此,由于您增加了父和子的耦合,因此您的实现难以维护。

我可以建议另外实施吗? lastUpdated字段应该表示特定域对象的更新时间。你正在寻找的日期并不完全相同,所以我不会试图以“错误”的方式使用现有的约定。听起来像父对象所需的日期是“孩子最后一次被修改”。

改为使用公式。

为此,您可以使用formula。使用公式,您可以得到您想要的,而无需直接修改父对象,您仍然可以使用动态查找器和其他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都会加载公式的值。现在,无论何时保存子项,父项都将具有该属性的准确值,而无需触及父项。

答案 1 :(得分: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字段,这要归功于映射中autoTimestamp设置为trueupdatedTrigger设置为可为空,因此它不会使任何现有数据库表无效,因此可以随时添加到任何域类。

答案 2 :(得分:0)

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

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)"
}