Прямой ответ
Необходимость установить отношения, т. Е. Назначать нос лицу и лицо узлу, не очень неудобна.Hibernate - это маппер RELATIONSHIP , поэтому вы должны сделать отношения явными.Тем не менее, вы можете написать меньше кода, определив
setNose(nose){
this.nose = nose
nose.face = this
}
на Face.Теперь, когда вы делаете face.nose = nose
, для вас вызывается сеттер, и отношения устанавливаются так, как вы хотите.
Общие полезные мысли
Как правило, вам не нужно назначать отношения в обоих направлениях.Вполне допустимо иметь однонаправленные или двунаправленные отношения.
Однако определение hasOne
имеет очень специфические значения.В документации очень четко говорится, что цель hasOne - указать hibernate поместить ключ, который определяет отношения в дочернем объекте, в данном случае Nose.Если вы внимательно об этом подумаете, вы поймете, что отношения должны быть двунаправленными.Вот некоторые мысли:
1) вы определяете hasOne на Face (то есть родитель).
2), даже если вы определили hasOne для родителя, базовая таблица, на которую влияют, является дочерней.таблица (т. е. столбец face_id на Nose)
3) Поскольку внешний ключ находится на дочернем элементе, дочерний элемент должен иметь ссылку на своего родителя.Если это не так, у вас будет дочернее свойство, которое является внешним ключом, но не связано с объектом.
4) Помните, что вы используете механизм ORM для определения отношений.Хотя вы можете вручную добавить поле face_id в Nose и настроить значения в коде (т. Е. Самостоятельно управлять отношениями, а не позволять инструменту ORM делать это), тот факт, что вы используете ORM в явном виде, означает, что инструмент ORM будет управлять отношениямидля вас.
РЕДАКТИРОВАТЬ - теперь, читая мой ответ, я не был убежден, поэтому я написал тест.Я определил классы Face и Nose, как показано в документации hasOne, но не определил Face на носу.Я пытался сделать это однонаправленным.Я написал тест, чтобы увидеть, что произойдет.Вот тест
class FaceTests extends GroovyTestCase {
public void testStuff(){
Face face = new Face()
Nose nose = new Nose()
face.nose = nose;
face.save(flush:true)
assertNotNull face.id
assertNotNull nose.id
}
}
, и результатом является исключение, содержащее
hasOne property [Face.nose] is not bidirectional. Specify the other side of the relationship!
. Таким образом, фреймворк даже гарантирует, что при использовании hasOne у вас будет двунаправленныйотношения.