#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
?