cascade = {"remove"} VS orphanRemoval = true VS ondelete = "CASCADE

93

J'ai essayé de rassembler quelques informations sur les méthodes suivantes pour supprimer automatiquement l'entité enfant lorsqu'une entité parente est supprimée. Il semble que la méthode la plus courante consiste à utiliser l'une de ces trois annotations: cascade = {"remove"} OR orphanRemoval = true OR ondelete = "CASCADE" .

Je suis un peu confus au sujet du troisième: ondelete = "CASCADE" , car les explications dans la doctrine, la documentation officielle sur celui-ci est très rare) et j'aimerais que quelqu'un puisse me confirmer les informations suivantes que j'ai recueillies et comprises de mes recherches sur le net et expérience ...

CE QU'IL FAIT

cascade = {"remove"}
==> l'entité du côté inverse est supprimée lorsque l'entité du côté propriétaire l'est. Même si vous êtes dans une multitude avec une autre entité propriétaire.
- doit être utilisé sur la collection (donc dans la relation OneToMany ou ManyToMany)
- implémentation dans l'ORM

orphanRemoval = true
==> l'entité du côté inverse est supprimée lorsque l'entité du côté propriétaire est ET elle n'est plus connectée à aucune autre entité côté propriétaire. (réf. doctrine official_doc - implémentation dans l'ORM
- peut être utilisé avec OneToOne, OnetoMany ou ManyToMany

onDelete = "CASCADE"
==> cela ajoutera On Delete Cascade à la colonne de clé étrangère dans la base de données
- Cette stratégie est un peu difficile à faire mais peut être très puissante et rapide. (réf. doctrine official_doc ... mais je n'ai pas lu plus d'explications)
- ORM doit faire moins de travail (par rapport aux deux méthodes précédentes) et devrait donc avoir de meilleures performances.

autres informations
- toutes ces 3 façons de faire sont implémentées sur des entités de relation bidirectionnelles (à droite ??? )
- en utilisant cascade = {"remove"} contourne complètement toute clé étrangère onDelete = CASCADE. (réf. doctrine_official_doc )

EXEMPLE D'UTILISATION DANS CODE

  • orphanRemoval et cascade = {"remove"} sont définis dans la classe d'entité inversée.
  • ondelete = "CASCADE" est défini dans l'entité propriétaire
  • vous pouvez aussi simplement écrire @ORM \ JoinColumn (onDelete = "CASCADE") et laisser la doctrine gérer les noms de colonnes

cascade = {"supprimer"}

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

orphanRemoval = true

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

onDelete = "CASCADE"

/** 
* @ManyToOne(targetEntity="Contact", inversedBy="phonenumbers")
* @JoinColumn(name="contact_id", referencedColumnName="contact_id", onDelete="CASCADE")
*/ 
protected $contact; 
Alexis_D
la source
1
il a une bonne explication stackoverflow.com/questions/25515007/…
Gregsparrow

Réponses:

61

onDelete="CASCADE"est géré par la base de données elle-même. cascade={"remove"}est géré par la doctrine.

onDelete="CASCADE"est plus rapide car les opérations sont effectuées au niveau de la base de données plutôt que par doctrine. La suppression est effectuée par le serveur de base de données et non par Doctrine. Avec cascade={"remove"}doctrine doit gérer l'entité elle-même et effectuera des vérifications supplémentaires pour voir si elle n'a pas d'autres entités propriétaires. Lorsqu'aucun autre n'existe, il supprimera l'entité. Mais cela crée des frais généraux.


cascade = {"supprimer"}

  • l'entité du côté inverse est supprimée lorsque l'entité du côté propriétaire l'est. Même si vous êtes dans une multitude avec une autre entité propriétaire. Non, si l'entité appartient à autre chose. Il ne sera pas supprimé.
  • doit être utilisé sur la collection (donc dans la relation OneToMany ou ManyToMany)
  • mise en œuvre dans l'ORM

orphanRemoval = "vrai"

  • l'entité du côté inverse est supprimée lorsque l'entité côté propriétaire est ET elle n'est plus connectée à aucune autre entité côté propriétaire. Pas exactement, cela fait que la doctrine se comporte comme si elle n'appartenait pas à une autre entité, et donc la supprime.
  • mise en œuvre dans l'ORM
  • peut être utilisé avec OneToOne, OnetoMany ou ManyToMany

onDelete = "CASCADE"

  • cela ajoutera On Delete Cascade à la colonne de clé étrangère DANS LA BASE DE DONNÉES
  • Cette stratégie est un peu difficile à mettre en œuvre mais peut être très puissante et rapide. (ceci est une citation du tutoriel officiel de doctrine ... mais je n'ai pas vu beaucoup plus d'explications)
  • ORM doit faire moins de travail (par rapport aux deux méthodes précédentes) et devrait donc avoir de meilleures performances.
Waaghals
la source
3
@ waaghals. À propos de vos commentaires sur la cascade = {"remove"} ==> J'ai une relation ManyToMany entre l'article d'entité et la catégorie. Lorsque je supprime un article ($ em-> remove ($ article);), il supprime toutes les catégories liées à cet article MÊME si ces catégories sont également liées à d'autres articles. donc je dirais qu'il ne se comporte pas comme vous écrivez.
Alexis_D
2
@ waaghals. À propos de vos commentaires sur orphanRemoval = "true" La phrase que j'ai écrite "l'entité du côté inverse est supprimée lorsque l'entité du côté propriétaire est, et elle n'est possédée par aucune autre entité" est citée des pages officielles de la doctrine. doctrine = suppression d'orphelin .
Alexis_D
1
@Alexis_D, entièrement d'accord avec vos commentaires La réponse est incorrecte et peut être vraiment déroutante pour les débutants
Stepan Yudin
3
L'un des exemples les plus clairs que j'ai lus: gist.github.com/pylebecq/f844d1f6860241d8b025
Victor S
Le lien de @VictorS est très clair. Je ne travaille plus avec Doctrine, alors je sens que je ne peux pas mettre à jour ma réponse sans savoir de première main comment cela fonctionne. Si quelqu'un pouvait mettre à jour ma réponse, ce serait formidable.
Waaghals