5

在 grails 中,我可以像这样实现 N:1 关系:

class Parent { hasMany = [children:Child] }
class Child  { belongsTo = [parent:Parent] }

现在(如果始终正确使用 addTo 和 removeFrom)我可以通过 parent.children 获得父母的孩子。

但我也可以不用hasMany:

class Parent { }
class Child  { belongsTo = [parent:Parent] }

然后我必须使用 Child.findAllByParent(parent) 来获取所有孩子。

我的问题:如果也可以用第二种方式查询父母的孩子,我应该使用 hasMany 有什么重要的原因吗?

我想有时只引用 parent.children 会更容易(如果与父母一起急切地获取可能会更快?),但另一方面,当有几个孩子时,这个列表可能会变得相当长。而我不喜欢 hasMany 的一点是,您总是必须注意 addTo 或 removeFrom 或者在添加一个带有 Parent 的新 Child 后清除会话,以便 grails 自动执行此操作......

如果孩子很少,你应该简单地使用 hasMany 并且如果有很多(出于性能原因)就不要使用它的答案,还是背后有更多?

4

2 回答 2

8

使用 hasMany 与 belongsTo 更相关于您希望在发生更新/删除时指定的级联行为。在您的第二个示例中,级联在子端设置为 ALL,在父端设置为 NONE。如果您删除一个孩子,则父母不会发生任何事情。如果删除父级,则所有子级将被自动删除。

在您的第一个示例中,级联在父端设置为 ALL,在子端设置为 SAVE-UPDATE。因此,现在您可以执行以下操作:

parent.addToChildren(child1)
parent.addToChildren(child2)
parent.addToChildren(child3)
parent.save(flush:true)

当您保存父级时,所有子级都将更新。

触及你没有问的东西,你也可能有类似的东西:

class Parent { hasMany = [children:Child] }
class Child  { Parent parent }

如果您以这种方式定义从 Child 到 Parent 的关系,您将需要在删除 parent* 时手动管理引用 parent 的 Child 对象。(*这更正了先前被证明不准确的陈述)

因此,hasMany/belongsTo 有两个主要考虑因素:

  1. 你想在更新/删除时执行什么样的级联策略
  2. 如果您希望需要为父母检索一组孩子,那么您最有可能如何访问数据,使用 parent.getChildren() 方法非常方便。

更新:

我还想澄清一下,当你使用 hasMany 时,GORM 不会急切获取;默认情况下,GORM 使用惰性获取策略,因此在尝试访问 parent.children 之前它不会获取孩子

如果您希望在默认情况下急切地获取关联,您可以指定适当的映射:

class Parent { 
  hasMany = [children:Child]
  static mapping = {
    children lazy:false
  }
}

最后,您提到您不喜欢必须担心 hasMany 端的 addTo/removeFrom。如果您使用 flush:true 保存,则不必这样做。

def parent = Parent.get(id)
def child = new Child(name:'child1', parent:parent)
if(child.save(flush:true)) {
  // both sides of the relationship should be good now
} 

编辑:修复了子/父级联默认值的颠倒顺序,并更正了关于 gorm 如何在没有 belongsTo 的情况下处理关系的误解

于 2010-06-29T16:40:51.487 回答
0

很好的问题,目前接受的答案很好。还有另一个重要的性能考虑因素,即添加和保存新子项时会发生什么。在您的第一个示例中,默认情况下,Grails 必须先从数据库加载整个子列表,然后再将新列表插入 Set,以保证唯一性。在第二种情况下,它没有,这会带来更好的性能。您可以通过按照http://grails.org/doc/latest/guide/single.html#sets,ListsAndMaps将子项定义为“集合”来解决第一个示例中的这种行为

于 2012-01-06T07:09:03.433 回答