В чашах Грааля я могу реализовать отношения 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 (родитель) для получения всех детей.
Мой вопрос: Есть ли какие-либо важные причины, почему я должен использовать hasMany, если может запросить дочерние элементы родителя вторым способом также?
Я предполагаю, что это иногда легче (и возможно быстрее, если нетерпеливо выбрано вместе с родителем?), чтобы просто относиться к parent.children но с другой стороны этот Список может стать довольно длинным, когда существует несколько детей. И что я не люблю приблизительно hasMany или - что всегда необходимо заботиться о addTo или removeFrom или очистить сессию после добавления нового Ребенка с Родителем так, чтобы чаши Грааля сделали это автоматически...
Ответ то, что необходимо просто использовать hasMany, если существует немного детей и не используют его, если существуют многие (по причинам производительности), или есть ли больше позади него?
Использование hasMany по сравнению с ownTo больше связано с каскадным поведением, которое вы хотите указать при обновлении / удалении.Во втором примере для каскадирования установлено значение ALL на дочерней стороне и NONE на родительской стороне. Если вы удалите дочерний элемент, с родителем ничего не произойдет. Если вы удалите родителя, все дочерние элементы будут автоматически удалены.
В вашем первом примере для каскадирования установлено значение ВСЕ на родительской стороне и SAVE-UPDATE на дочерней стороне.Итак, теперь вы можете сделать что-то вроде:
parent.addToChildren(child1)
parent.addToChildren(child2)
parent.addToChildren(child3)
parent.save(flush:true)
И когда вы сохраните родительский элемент, все дочерние элементы будут обновлены.
Касаясь того, о чем вы не спрашивали, вы, вероятно, также можете получить что-то вроде:
class Parent { hasMany = [children:Child] }
class Child { Parent parent }
Если вы определите отношение от дочернего к родительскому таким образом, вам нужно будет вручную управлять дочерними объектами, которые ссылаются на родительский элемент, когда вы удаляете родительский *. (* это исправляет предыдущее утверждение, которое оказалось неточным)
Итак, hasMany / ownTo имеет два основных аспекта:
ОБНОВЛЕНИЕ:
Я также хочу уточнить, что GORM не будет загружать данные, когда вы используете hasMany; по умолчанию GORM использует стратегию отложенной выборки, поэтому он не получит дочерние элементы, пока не попытается получить доступ к parent.children
. Если вы хотите, чтобы ассоциация извлекалась быстро по умолчанию, вы можете указать соответствующее сопоставление:
class Parent {
hasMany = [children:Child]
static mapping = {
children lazy:false
}
}
Наконец, вы упомянули, что вам не нравится, что вам нужно беспокоиться о addTo / removeFrom на стороне hasMany. Вам не нужно этого делать, если вы сохраняете с помощью 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 обрабатывает отношения без ownTo