cascade = {«удалить»} VS orphanRemoval = true VS ondelete = "КАСКАД

94

Я попытался собрать немного информации о следующих способах автоматического удаления дочернего объекта при удалении родительского объекта. Кажется, что наиболее распространенный способ - использовать одну из этих трех аннотаций: cascade = {"remove"} ИЛИ orphanRemoval = true ИЛИ ondelete = "CASCADE" .

Я немного сбит с толку насчет третьего: ondelete = "CASCADE" , поскольку объяснений в официальной документации доктрины об этом очень мало), и я был бы рад, если бы кто-нибудь мог подтвердить мне следующую информацию, которую я собрал и понял из моего исследования сеть и опыт ...

ЧТО ОНО ДЕЛАЕТ

cascade = {"remove"}
==> объект на обратной стороне удаляется, когда объект на стороне-владельце удаляется. Даже если вы находитесь во множестве компаний с другой стороной-владельцем.
- следует использовать при сборе (например, в отношениях OneToMany или ManyToMany)
- реализация в ORM

orphanRemoval = true
==> сущность на обратной стороне удаляется, когда сущность на стороне-владельце является И она больше не связана с какой-либо другой сущностью на стороне-владельце. (см. doctrine official_doc - реализация в ORM
- может использоваться с OneToOne, OnetoMany или ManyToMany

onDelete = "CASCADE"
==> это добавит каскад при удалении в столбец внешнего ключа в базе данных.
Эту стратегию немного сложно реализовать, но она может быть очень мощной и быстрой. (см. doctrine official_doc ... но не читал больше объяснений)
- ORM должен выполнять меньше работы (по сравнению с двумя предыдущими способами) и, следовательно, должен иметь лучшую производительность.

другая информация
- все эти 3 способа реализованы на объектах с двунаправленным отношением ( верно ??? )
- использование cascade = {"remove"} полностью обходит любой внешний ключ onDelete = CASCADE. (см. doctrine_official_doc )

ПРИМЕР, КАК ИСПОЛЬЗОВАТЬ В КОДЕ

  • orphanRemoval и cascade = {"remove"} определены в инвертированном классе сущности.
  • ondelete = "CASCADE" определяется в сущности владельца
  • вы также можете просто написать @ORM \ JoinColumn (onDelete = "CASCADE") и позволить доктрине обрабатывать имена столбцов

cascade = {"удалить"}

/**
* @OneToMany(targetEntity="Phonenumber", mappedBy="contact", cascade={"remove"})
*/
protected $Phonenumbers

orphanRemoval = true

/**
* @OneToMany(targetEntity="Phonenumber", mappedBy="contact", orphanRemoval=true)
*/
protected $Phonenumbers

onDelete = "КАСКАД"

/** 
* @ManyToOne(targetEntity="Contact", inversedBy="phonenumbers")
* @JoinColumn(name="contact_id", referencedColumnName="contact_id", onDelete="CASCADE")
*/ 
protected $contact; 
Alexis_D
источник
1
у него есть хорошее объяснение stackoverflow.com/questions/25515007/…
Gregsparrow

Ответы:

63

onDelete="CASCADE"управляется самой базой данных. cascade={"remove"}управляется доктриной.

onDelete="CASCADE"быстрее, потому что операции выполняются на уровне базы данных, а не доктриной. Удаление выполняется сервером базы данных, а не Doctrine. With cascade={"remove"}doctrine должен управлять самой сущностью и выполнять дополнительные проверки, чтобы увидеть, нет ли у нее других сущностей-владельцев. Если другого не существует, он удалит объект. Но это создает накладные расходы.


cascade = {"удалить"}

  • сущность на обратной стороне удаляется, когда сущность на стороне-владельце удаляется. Даже если вы находитесь во множестве компаний с другой стороной-владельцем. Нет, если объект принадлежит другому лицу. Он не будет удален.
  • следует использовать при сборе (так в отношениях OneToMany или ManyToMany)
  • реализация в ORM

orphanRemoval = "правда"

  • сущность на обратной стороне удаляется, когда сущность на стороне-владельце является И она больше не связана с какой-либо другой сущностью на стороне-владельце. Не совсем так, это заставляет учение вести себя так, как будто оно не принадлежит другому лицу, и таким образом удаляет его.
  • реализация в ORM
  • можно использовать с OneToOne, OnetoMany или ManyToMany

onDelete = "КАСКАД"

  • это добавит On Delete Cascade в столбец внешнего ключа В БАЗЕ ДАННЫХ
  • Эту стратегию немного сложно реализовать, но она может быть очень мощной и быстрой. (это цитата из официального учебника доктрины ... но не видел более подробных объяснений)
  • ORM должен выполнять меньше работы (по сравнению с двумя предыдущими способами) и, следовательно, должен иметь лучшую производительность.
Waaghals
источник
3
@ waaghals. О ваших комментариях к cascade = {"remove"} ==> У меня есть отношение ManyToMany между статьей и категорией объекта. Когда я удаляю статью ($ em-> remove ($ article);), она удаляет все категории, связанные с этой статьей, ДАЖЕ, если эти категории также связаны с другими статьями. поэтому я бы сказал, что он не ведет себя так, как вы пишете.
Alexis_D
2
@ waaghals. О ваших комментариях к orphanRemoval = "true" Предложение, которое я написал, "сущность на обратной стороне удаляется, когда сущность на стороне-владельце, и она не принадлежит никаким другим сущностям" цитируется с официальных страниц доктрины. Доктрина = сиротское удаление .
Alexis_D
1
@Alexis_D, полностью согласен с вашими комментариями Ответ неверен и может сбивать с толку новичков
Степан Юдин
3
Один из наиболее ярких примеров, которые я читал: gist.github.com/pylebecq/f844d1f6860241d8b025
Victor S
Ссылка @VictorS очень четкая. Я больше не работаю с Doctrine, поэтому чувствую, что не могу обновить свой ответ, не зная из первых рук, как это работает. Если бы кто-то мог обновить мой ответ, это было бы здорово.
Waaghals