【问题标题】:Removing children from entity with self-referencing One-to-Many association从具有自引用一对多关联的实体中删除子项
【发布时间】:2012-10-24 09:54:07
【问题描述】:

我在由“父”映射并由“子”反转的实体(用户)上具有自引用的一对多关联。我希望能够删除不是父母的用户。我的实体声明如下。

class User implements UserInterface
{
   /**
    * @ORM\Column(name="id", type="smallint")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
   protected $id;

   (...)

   /**
    * @ORM\OneToMany(targetEntity="User", mappedBy="parent")
    */
   protected $children;

   /**
    * @ORM\ManyToOne(targetEntity="User", inversedBy="children")
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
    */
   protected $parent;

   public function __construct()
   {
       $this->parentId = null; // Default value for column parent_id
       $this->children = new ArrayCollection();
   }
}

当我尝试删除不是父级的子用户时,我收到以下错误。

带有消息“SQLSTATE[23000] 的异常“PDOException”:违反完整性约束:1451 无法删除或更新父行:外键约束失败

我试过做级联删除,如下。

/**
 * @ORM\OneToMany(targetEntity="User", mappedBy="parent", cascade={"persist", "remove"})
 */
protected $children;

无论哪种方式都会出现相同的错误。有什么帮助吗?

【问题讨论】:

    标签: symfony doctrine-orm mapping self-reference


    【解决方案1】:

    使用这个:

    /**
    * @ORM\ManyToOne(
    *     targetEntity="User", 
    *     inversedBy="children", 
    *     cascade={"persist", "remove"}
    * )
    *
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
    */
    

    onDelete="SET NULL" 所做的是,当您删除父元素时,其子元素将在 parent_id 列中获得 NULL 值。这发生在数据库级别,所以你必须学说:模式:更新。

    【讨论】:

    • 我进行了更改,db 将删除规则显示为“SET NULL”,以用于运行学说:模式:更新的 FK 约束。我还取消了 cascade={'remove'}。但是,删除子用户也会删除父用户,如果我以该父用户身份登录,我会得到 InvalidArgumentException: You cannot refresh a user from the EntityUserProvider that does not contain an identifier 现在,我我试图删除一个孩子,用户不是父用户。谢谢。
    • 也尝试在操作中执行此操作。 $parentUser->removeChild($childUser); $em->persist($childUser); $em->persist($parentUser); $em->remove($childUser); $em->flush(); 那也不行。 CASCADE 和 SET NULL 在删除子用户时都会删除父用户。
    • 删除cascade={"persist", "remove"}。这有点奇怪,因为我有类似的关系并且一切正常。为了能够从父级中删除子级,您必须输入:@ORM\OneToMany(targetEntity="User", mappedBy="parent", cascade={"all"})。如果可行,请尝试 cascade={"persist"} (而不是 "all"),如果这也可行(最好减少它)。如果一切都失败了,那么你必须通过单元测试来做到这一点。
    • 试过了,当我删除孩子时,它仍在删除父用户。我现在有 cascade={"persist"} 用于子属性,onDelete="SET NULL" 用于父属性。有人想从我这里得到更多信息来帮助我解决这个问题吗?谢谢。
    • 除了您之外,我没有看到任何其他方法可以进行单元测试来解决它。这比手动刷新页面、更改数据库等要快得多。
    【解决方案2】:

    最后,我设法在保留父类别的同时删除了一个子类别:

    $parent = $em->getRepository('Category\Entity\Category')->find(1);//parent id
    $child = $em->getRepository('Category\Entity\Category')->find(5);// child id
    $parent->removeChild($child);
        $em->persist($child);
        $em->remove($child);
        $em->persist($parent);      
        $em->flush(); 
    

    【讨论】:

      【解决方案3】:

      cascade 必须在owning side 上:

      /**
       * @ORM\ManyToOne(
       *     targetEntity="User", 
       *     inversedBy="children", 
       *     cascade={"persist", "remove"}
       * )
       */
      protected $parent;
      

      【讨论】:

      • 我试过了,但在尝试删除子用户时遇到了同样的错误。此外,我不希望在删除父用户时删除子用户,它们可以作为孤立元素继续存在。当我检查时,将“级联”添加到拥有方并使用控制台命令更新我的架构对实际的数据库架构没有影响。会不会是个问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 2013-11-06
      • 1970-01-01
      相关资源
      最近更新 更多