Моделирование дерева «многие к одному» в grails

#grails #grails-orm #grails-2.0 #grails-domain-class

#grails #grails-orm #grails-2.0 #grails-domain-class

Вопрос:

Я пытаюсь смоделировать организационное дерево в grails. То, что у меня есть, работает, но у меня есть пара вопросов по этому поводу.

Вот мой класс «Организация»:

 class Organization {

  String title
  Organization parentOrg

  static hasMany = [ childOrg: Organization ]

  static mappedBy = [ 
    childOrg: 'parentOrg',
    parentOrg: 'childOrg'
  ]

  static constraints = {
    parentOrg nullable: true
  }
}
  

Теперь, когда я создаю новую «Организацию», подобную этой:

 def newOrg = new Organization(
    title: 'New Organization',
    parentOrg: oldOrg).save()
  

Все работает хорошо, и связь с родительским элементом, похоже, смоделирована правильно.

Но если я попытаюсь вызвать что-то вроде oldOrg.childOrg.each , я не получу никаких результатов, если я также не вызвал oldOrg.addToChildOrg(newOrg) .

Более того, когда я проверяю созданные таблицы, единственной ссылкой на это отношение является parent_org_id столбец в Organization таблице.

Теперь я понимаю, что это все, что необходимо для определения childOrg отношений, но я не замечаю никаких изменений в базе данных с момента до моего вызова oldOrg.addToChildOrg(newOrg) до после!

Итак, где сохраняется это отношение при вызове addToChildOrg , когда я не вижу никаких изменений в базе данных?

Кроме того, как я могу настроить это отношение, чтобы автоматически создавать childOrg отношение при добавлении parentOrg ? Я не думаю, что мне нужно вызывать, addToChildOrg когда я добавляю parentOrg . Это должно подразумеваться.

Спасибо!

Ответ №1:

Используйте hasOne ассоциацию для хранения ссылки на внешний ключ в двунаправленном виде «один к одному».

Поскольку вы не хотите каждый раз добавлять связь с другой стороны, поэтому вы можете создать сеттер для облегчения вашей работы, например-

 setParentOrg(parentInstance){
   this.parentOrg = parentInstance
   parentInstance.childOrg = this
}
  

Теперь, когда вы это делаете organisationInstance.parentOrg = parentInstance , для вас вызывается установщик, и связь настраивается так, как вы хотите.

Комментарии:

1. Это может помочь избавиться от необходимости также вызывать .addToChildOrg , но где это отношение хранится в базе данных? Указывая, mappedBy = [childOrg: 'parentOrg'] я получаю, что childOrg основан на столбце parentOrg, но что меняется после вызова .addToChildOrg ? В базе данных ничего такого, что я могу видеть. Спасибо за ваше предложение!

Ответ №2:

если я прав, вам не хватает определения belongsTo, потому что вам нужно определить, что каждый экземпляр Organization принадлежит его экземпляру parentOrg .

попробуйте это объявление класса:

 class Organization {

  String title
  Organization parentOrg

  static belongsTo = [parentOrg: Organization]
  static hasMany = [ childOrg: Organization ]
  static mappedBy = [ childOrg: 'parentOrg']

  static constraints = {
    parentOrg nullable: true
  }
}
  

Комментарии:

1. Это также не имеет никакого эффекта. Единственное, что сохранилось в базе данных, — это Organization таблица вместе с parent_org_id столбцом. В базе данных нет ссылки на childOrg , а дочерняя ссылка не создается, если я не укажу addToChildOrg() . Что тоже странно, потому что вызов addToChildOrg() работает, но в базу данных ничего дополнительно не добавлено или вообще нет дополнительной области, где эта информация могла бы храниться!

2. Понятно, то есть вы имеете в виду, что не можете найти childOrg в базе данных? Но, используя, static mappedBy = [ childOrg: 'parentOrg'] вы сказали hibernate, что это childOrg будет отображено parent_org_id , и hibernate загружает вашу коллекцию дочерних элементов, подобных SELECT * FROM organization WHERE parent_org_id = :this.id . Если вы хотите увидеть их в базе данных , просто удалите mappedBy и добавьте joinTable в сопоставление

3. Верно, но когда я создаю Organization с parentOrg: oldOrg дочерней ассоциацией, она не работает, если я также не вызываю oldOrg.addToChildOrg(newOrg) . Разве добавление родительского элемента не должно подразумевать дочернее отношение? Особенно с mappedBy ?