更新;“最新更新”;Grails中父域类中的字段
我有一个父域类,该类有另一个域类的更新;“最新更新”;Grails中父域类中的字段,grails,gorm,grails-domain-class,Grails,Gorm,Grails Domain Class,我有一个父域类,该类有另一个域类的hasMany。父域类和子域类都有lastUpdated和dateCreated字段。我的问题是,当我更新子域类时,我需要父域类反映该更改并更新其lastUpdated字段 Grails提供的父级和子级之间是否存在实现此功能的映射或其他配置 更新 我向子域类添加了以下行: def beforeUpdate = { parent.lastUpdated = new Date() } 我还必须确保在控制器中,当我更新一个子项时,我还必须保存父项以保留新的l
hasMany
。父域类和子域类都有lastUpdated
和dateCreated
字段。我的问题是,当我更新子域类时,我需要父域类反映该更改并更新其lastUpdated
字段
Grails提供的父级和子级之间是否存在实现此功能的映射或其他配置
更新
我向子域类添加了以下行:
def beforeUpdate = {
parent.lastUpdated = new Date()
}
我还必须确保在控制器中,当我更新一个子项时,我还必须保存父项以保留新的
lastUpdated
字段。这似乎很好,但我仍然想知道是否有映射或类似的东西可以做到这一点。我感觉您建议的实现将有缺陷。您通过手动设置lastUpdated
日期来更新parent
,这可能会导致grails在对其执行脏检查后再次更新lastUpdated
。如果是这样的话,你最终会得到一个上次更新的时间,它发生在你最初设定的日期之后。在您的测试中,这可能只有几(毫秒)秒,但您不能保证这一点
不仅如此,您的实现更难维护,因为您增加了父级和子级的耦合
我可以建议另一种实现方式吗?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都会在中加载公式的值。现在,无论何时保存一个子项,父项都将拥有该属性的准确值,而不必接触父项。在我的一个项目中,域是这样的。 一个程序有很多AdvertisingMaterial,我们有AdvertisingMaterial、FlashAd、ImageAd等子类。用户希望能够过滤包含flashAds、imageAds等的程序。现在我需要根据数据库表中的类属性进行过滤(当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)"
}
ListadMaterials=advisingmaterial.findAllByClassName(“com.project.FlashAd”)
静态映射={
全名公式:“CONCAT(名字、姓氏)”
totalAmount公式:“总和(金额)”
}
我用了一个黑客。我在我的父类域类中添加了一个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
被设置为可空,这样它就不会使任何现有数据库表无效,因此可以随时添加到任何域类。“我还必须确保在控制器中,当我更新子级时,我还必须保存父级”。使用Grails 2.2.0,beforeUpdate技术可以工作。不需要保存父级,也不会出现任何双重保存行为。所以你不需要任何公式,只需要听众。他真的有效吗?我以前没有试过,或者我在任何地方见过这种类型的东西了。。。!!!对不起,我给了你一个否决票:建议OP的解决方案有效,而你的感觉是错误的。这个公式带来了很多新的变化:孩子们也有时间戳,如果你的父实体没有被刷新和再次查询,这个公式可能不会被调用……我认为这里的观点是正确的。您不应该真正修改lastUpdated的实现,因为您不知道它还依赖于什么。我认为这最终是一个优雅的解决方案。但是,我认为代码示例中有一个错误,我现在将更新它。这个例子并不是像用户Guillaume建议的那样存储一个额外的列,该列只是您访问公式值的方式。@Guillaume,也许“感觉”不是这里最好使用的词。我得到的是Daniel Bower的建议——这种更新方式现在可能有效,但你打破了Grails设定的惯例,这意味着它在未来可能不起作用。我同意使用您指出的公式的缺点,但这些问题取决于实现,而不是框架。