Когда hasMany должен использоваться для отношений N:1 в классах домена чаш Грааля?

В чашах Грааля я могу реализовать отношения 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, если существует немного детей и не используют его, если существуют многие (по причинам производительности), или есть ли больше позади него?

5
задан Jörg Brenninkmeyer 29 June 2010 в 14:59
поделиться

1 ответ

Использование 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 имеет два основных аспекта:

  1. Какую каскадную стратегию вы хотите применять при обновлениях / удалениях
  2. Как вы скорее всего, вы собираетесь получить доступ к данным, если вы ожидаете, что вам потребуется получить набор дочерних элементов для родителя, наличие метода parent.getChildren () довольно удобно.

ОБНОВЛЕНИЕ:

Я также хочу уточнить, что 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

8
ответ дан 14 December 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: