什么时候应该使用grails域类中的N:1关系?

Jör*_*yer 5 orm grails hibernate grails-domain-class

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

class Parent { hasMany = [children:Child] }
class Child  { belongsTo = [parent:Parent] }
Run Code Online (Sandbox Code Playgroud)

现在(如果总是正确使用addTo和removeFrom)我可以通过parent.children获取Parent的子项.

但我也可以在没有hasMany的情况下做到这一点:

class Parent { }
class Child  { belongsTo = [parent:Parent] }
Run Code Online (Sandbox Code Playgroud)

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

我的问题:如果能以第二种方式查询父母的孩子,我有什么理由可以使用hasMany吗?

我想它有时更容易(也许更快,如果与父母一起渴望获取?)只是引用parent.children,但另一方面,当有几个孩子时,这个List会变得相当长.而我不喜欢的事情还有很多,你总是需要注意addTo或removeFrom,或者在添加一个带有Parent的新Child之后清除会话,以便grails自动执行此操作...

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

pro*_*lux 8

使用hasMany与belongsTo更相关的是在更新/删除发生时要指定的级联行为.在第二个示例中,级联在子端设置为ALL,在父端设置为NONE.如果删除子项,则父项不会发生任何事情.如果删除父项,则会自动删除所有子项.

在您的第一个示例中,级联在父级设置为ALL,在子级端设置为SAVE-UPDATE.所以现在你可以这样做:

parent.addToChildren(child1)
parent.addToChildren(child2)
parent.addToChildren(child3)
parent.save(flush:true)
Run Code Online (Sandbox Code Playgroud)

当您保存父母时,所有孩子都将被更新.

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

class Parent { hasMany = [children:Child] }
class Child  { Parent parent }
Run Code Online (Sandbox Code Playgroud)

如果以这种方式定义从Child到Parent的关系,则需要在删除父*时手动管理引用父对象的Child对象.(*这纠正了之前证明不准确的陈述)

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

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

更新:

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

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

class Parent { 
  hasMany = [children:Child]
  static mapping = {
    children lazy:false
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,你提到你不喜欢你必须担心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
} 
Run Code Online (Sandbox Code Playgroud)

编辑:修复了子/父级联默认的逆序并纠正了关于gorm如何处理没有belongsTo的关系的错误观念