我有一个父域类,其中包含另一个域类的hasMany
。父域和子域类都包含lastUpdated
和dateCreated
字段。我的问题是,当我更新子域类时,我需要父域类来反映该更改并更新其lastUpdated
字段。
Grails提供的实现此功能的父级和子级之间是否有任何映射或其他配置?
更新
我在子域类中添加了以下行:
def beforeUpdate = {
parent.lastUpdated = new Date()
}
我还必须在控制器中确保当我更新孩子时,我还必须保存父母以保持新的lastUpdated
字段。这似乎工作正常,但我仍然想知道是否有映射或类似的东西会这样做。
答案 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
设置为true
。 updatedTrigger
设置为可为空,因此它不会使任何现有数据库表无效,因此可以随时添加到任何域类。
答案 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)"
}