简体   繁体   English

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

[英]Update “lastUpdated” Field in Parent Domain Class in Grails

I have a parent domain class the has a hasMany of another domain class. 我有一个父域类,它有一个hasMany的另一个域类。 Both the parent and the child domain classes have the lastUpdated and the dateCreated fields. 父域和子域类都具有lastUpdateddateCreated字段。 My issue is that when I update a child domain class, I need the parent domain class to reflect that change and update its lastUpdated field as well. 我的问题是,当我更新子域类时,我需要父域类来反映该更改并更新其lastUpdated字段。

Is there any mapping or other configuration between the parent and child that Grails provides that would implement this feature? Grails提供的父和子之间是否有任何映射或其他配置可以实现此功能?

Update 更新

I added the following lines to the child domain class: 我将以下行添加到子域类:

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

I also had to make sure in the controller that when I updated a child, I also had to save the parent as well to persist the new lastUpdated field. 我还必须在控制器中确保当我更新一个孩子时,我还必须保存父母以保持新的lastUpdated字段。 This seems to work fine, but I would still like to know if there is a mapping or something similar that would do this. 这似乎工作正常,但我仍然想知道是否有映射或类似的东西会这样做。

I have a feeling your suggested implementation will be buggy. 我有一种感觉,你建议的实施将是错误的。 You're updating the parent by setting the lastUpdated date manually, which might cause grails to update lastUpdated again after it does dirty checking on it. 您通过手动设置lastUpdated日期来更新parent ,这可能会导致grails在对其进行脏检查后再次更新lastUpdated If that's the case, you would actually end up with a lastUpdated time that occurred after the date you original set. 如果是这种情况,您实际上最终会得到在原始设置日期之后发生的lastUpdated时间。 In your testing, this might be only a few (milli)seconds, but you can't guarantee that. 在您的测试中,这可能只有几(毫秒)秒,但您无法保证。

Not only that, but your implementation is harder to maintain since you have increased the coupling of Parent and Child. 不仅如此,由于您增加了Parent和Child的耦合,因此您的实现难以维护。

Might I suggest another implementation? 我可以建议另一个实现吗? The lastUpdated field is supposed to represent the time the specific domain object was updated. lastUpdated字段应该表示特定域对象的更新时间。 The date you're looking for is not quite the same thing, so I wouldn't try to use the existing convention in the "wrong" way. 你正在寻找的日期并不完全相同,所以我不会试图以“错误”的方式使用现有的约定。 It sounds like the date you want for the parent object is "the last time a child was modified". 听起来像父对象所需的日期是“孩子最后一次被修改”。

Use a formula instead. 请改用公式。

To do that, you could use a formula . 为此,您可以使用公式 With a formula, you get exactly what you want without having to directly modify the parent object, and you can still use dynamic finders and other Grails sugar. 使用公式,您可以得到您想要的,而无需直接修改父对象,您仍然可以使用动态查找器和其他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 will load the value of the formula in whenever you read the object from the database. 无论何时从数据库中读取对象,GORM都会加载公式的值。 Now, whenever you save a Child, the parent will have an accurate value for that property without having to touch the Parent. 现在,无论何时保存子项,父项都将具有该属性的准确值,而无需触及父项。

I used a hack. 我用了一个黑客。 I have added a Long updateTrigger field to my parent domain class and a touch method: 我在我的域类和touch方法中添加了一个Long updateTrigger字段:

class Parent {
    Long updateTrigger

    static mapping = {
        autoTimestamp true
    }

    static constraints = {
        updateTrigger(nullable:true)
    }

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

In the update/save actions of the child controller, I just call: 控制器的更新/保存操作中,我只需调用:

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

This will increment the updateTrigger value, and the save() will automatically update the lastUpdated field thanks to the autoTimestamp set to true in the mapping. 这将增加updateTrigger值,并且由于映射中autoTimestamp设置为truesave()将自动更新lastUpdated字段。 updatedTrigger is set to be nullable so that it doesn't invalidate any existing database table and therefore can be added anytime to any domain class. updatedTrigger设置为可为空,因此它不会使任何现有数据库表无效,因此可以随时添加到任何域类。

In one of my project where the domain was like. 在我的项目中,域名就像。 A Program has many AdvertisingMaterial and we have subclasses of AdvertisingMaterial, FlashAd, ImageAd etc. The user want the ability to filter the programs which has flashAds, imageAds etc. Now I need to do the filtering on the basis of the class property that we have in database table (When table tablePerHierarchy is true). 一个程序有很多AdvertisingMaterial,我们有AdvertisingMaterial,FlashAd,ImageAd等的子类。用户希望能够过滤具有flashAds,imageAds等的程序。现在我需要根据我们拥有的类属性进行过滤在数据库表中(当table tablePerHierarchy为true时)。 So I did some changes in my domain class to get this property. 所以我在我的域类中进行了一些更改以获取此属性。

class AdvertisingMaterial {
        String className

        static constraints = {
                className(nullable: true)
        }

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

Now what I can use this className field in my dynamic finders and criteria query as well. 现在我可以在动态查找器和条件查询中使用此className字段。 So I can do something like 所以我可以做点什么

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

static mapping = {
               fullName formula: "CONCAT(FIRST_NAME,'  ',LAST_NAME)"
               totalAmount formula: "SUM(AMOUNT)"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM