级联=“删除” VS orphanRemoval=true VS ondelete="CASCADE

Posted

技术标签:

【中文标题】级联=“删除” VS orphanRemoval=true VS ondelete="CASCADE【英文标题】:cascade="remove" VS orphanRemoval=true VS ondelete="CASCADE级联=“删除” VS orphanRemoval=true VS ondelete="CASCADE 【发布时间】:2015-02-12 20:52:32 【问题描述】:

我尝试收集有关以下方式的一些信息,以在删除父实体时自动删除子实体。似乎最常见的方法是使用这三个注释之一:cascade="remove" OR orphanRemoval=true OR ondelete="CASCADE"

我对第三个有点困惑:ondelete="CASCADE",因为学说官方文档中关于这个的解释非常少),如果有人可以向我确认以下信息,我会很高兴我从我对网络的研究和经验中收集并了解...

它有什么作用?

cascade="remove" ==> 当拥有方实体存在时,反方实体被删除。即使您与其他拥有方实体在ManyToMany 中。

应该用于集合(所以在OneToManyManyToMany 关系中) 在 ORM 中的实现

orphanRemoval=true ==> 当拥有方实体是并且它不再连接到任何其他拥有方实体时,反面的实体将被删除。 (参考doctrine official_doc

在 ORM 中的实现 可与OneToOneOneToManyManyToMany 一起使用

onDelete="CASCADE" ==> 这会将 On Delete Cascade 添加到数据库中的外键列

此策略要正确执行有点棘手,但可以非常强大且快速。 (参考doctrine official_doc ...但还没有阅读更多解释) ORM 需要做的工作更少(与之前的两种方法相比),因此应该有更好的性能。

其他信息

所有这 3 种方式都是在双向关系实体上实现的(对???) 使用cascade="remove" 完全绕过任何外键onDelete=CASCADE。 (参考doctrine_official_doc)

如何在代码中使用它的示例

orphanRemovalcascade="remove" 在倒置实体类中定义。 ondelete="CASCADE" 在所有者实体中定义 您也可以只写@ORM\JoinColumn(onDelete="CASCADE") 并让教条处理列名

cascade="remove"

/**
* @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; 

【问题讨论】:

有很好的解释***.com/questions/25515007/… 【参考方案1】:

onDelete="CASCADE" 由数据库本身管理。 cascade="remove" 由学说管理。

onDelete="CASCADE" 更快,因为操作是在数据库级别执行的,而不是通过学说。删除是由数据库服务器而不是 Doctrine 执行的。对于cascade="remove",学说必须管理实体本身,并将执行额外检查以查看它是否没有任何其他拥有实体。当不存在其他实体时,它将删除该实体。但这会产生开销。


cascade="remove"

当拥有方实体是时,反方实体被删除。即使您与其他拥有方实体处于多对多关系中。 不,如果实体归其他人所有。它不会被删除。 应该用于集合(在 OneToMany 或 ManyToMany 关系中) 在 ORM 中的实现

orphanRemoval="true"

当拥有方实体为 AND 它不再连接到任何其他拥有方实体时,反向方的实体将被删除。 不完全是,这会使教义表现得像不属于其他实体一样,因此将其删除。 在 ORM 中的实现 可与 OneToOne、OnetoMany 或 ManyToMany 一起使用

onDelete="CASCADE"

这会将 On Delete Cascade 添加到数据库中的外键列中 此策略要正确执行有点棘手,但可以非常强大且快速。 (这是从学说官方教程中引用的……但没有看到更多解释) ORM 需要做的工作更少(与前两种方法相比),因此性能应该更好。

【讨论】:

@waaghals。关于级联上的 cmets="remove" ==> 我在实体文章和类别之间存在多对多关系。当我删除一篇文章 ($em->remove($article);) 时,它会删除所有链接到这篇文章的类别,即使这些类别也链接到其他文章。所以我会说它不像你写的那样表现。 @waaghals。关于你在 orphanRemoval="true" 上的 cmets 我写的句子“当拥有方实体是时,反面的实体被删除,并且它不被任何其他实体拥有”引用自学说官方页面。 doctrine=orphanremoval. @Alexis_D,完全同意你的 cmets 答案是不正确的,对于新手来说真的很困惑 我读过的一个更清晰的例子:gist.github.com/pylebecq/f844d1f6860241d8b025 @VictorS 的链接非常清晰。我不再使用 Doctrine,所以如果不知道第一手资料是如何工作的,我就无法更新我的答案。如果有人可以更新我的答案,那就太好了。

以上是关于级联=“删除” VS orphanRemoval=true VS ondelete="CASCADE的主要内容,如果未能解决你的问题,请参考以下文章

JPA/Hibernate 级联删除不起作用

已删除的对象将通过级联重新保存(从关联中删除已删除的对象)

在@OneToMany 中实现 orphanRemoval

学说: cascade="remove" vs orphanRemoval=true

请问hibernate级联更新时并不删除子表数据,只是将其外键置为null,是怎么回事?

Hibernate 从 onetomany 中删除