删除实体时重叠的实体关联导致数据库外键约束错误

时间:2014-05-07 21:20:58

标签: php mysql symfony doctrine-orm

我需要一些帮助来理解cascade如何与Symfony2实体关联一起使用,特别是“删除”选项。因为当我尝试删除实体时,存在数据库外键冲突,它不会从数据库中删除。

我有两个测试实体:

/**
* @ORM\Entity
* @ORM\Table(name="test")
*/
class Test extends Entity\Base {

    /**
    * This is a OneToOne Unidirectional association, just so that we can get the
    * current published version easily, based on the publishedId.
    * @ORM\OneToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\TestVersion")
    * @ORM\JoinColumn(name="publishedId", referencedColumnName="id")
    */
    protected $published;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    protected $publishedId = NULL;

    /**
     * This is the regular OneToMany Bi-Directional Association, for all the versions.
 * @ORM\OneToMany(targetEntity="\Gutensite\CmsBundle\Entity\View\TestVersion", mappedBy="view", cascade={"persist", "remove"}, orphanRemoval=true)
 */
protected $versions;
}

/**
* @ORM\Entity
* @ORM\Table(name="test_version")
*/
class TestVersion extends Entity\Base {


    /**
    * @ORM\ManyToOne(targetEntity="\Gutensite\CmsBundle\Entity\View\Test", inversedBy="versions")
    * @ORM\JoinColumn(name="viewId", referencedColumnName="id")
    */
    protected $view;

    /**
    * The primary view entity that this version belongs to.
    * @ORM\Column(type="integer", nullable=true)
    */
    protected $viewId;

}

*注意:我最初的双向OneToOne关系有cascade = {“persist”,“remove”},但意识到这是不需要的。无论哪种方式,问题都完全相同。

在控制器中,我创建了一个这样的测试实体:

$view = new Test();
$version = new TestVersion();
// associate the version with the view
$view->addVersion($version);
// mark this version as the published version (this is where the problem happens, though)
$view->setPublished($version);
$em->persist($view);
$em->flush();

这会在test_version中为test和一个关联版本创建一条主记录:

|---------------------|
| table: test         |
|---------------------|
| id    | publishedId |
| 100   |   500       |
|---------------------|

|---------------------|
| table: test_version |
|---------------------|
| id    | viewId |
| 500   |   100       |
|---------------------|

*注意:test_version.viewId是通过我的test.addVersion()方法手动设置的,该方法调用$ version-> setView($ this)。

但是当我去测试时删除主要实体时:

$view = $em->getRepository("GutensiteCmsBundle:View\Test")->find($request->query->get('id'));
$em->remove($view);
$em->flush();

它尝试删除主测试实体但失败,因为它被test_version.viewId引用。

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`cms`.`test_version`, CONSTRAINT `FK_635D070BCEB972AA` FOREIGN KEY (`viewId`) REFERENCES `test` (`id`))

如果我手动尝试删除数据库中的test_version记录,它也会因类似错误而失败:

ERROR 1451: 1451: Cannot delete or update a parent row: a foreign key constraint fails (`cms`.`test`, CONSTRAINT `FK_D87F7E0C628CCE00` FOREIGN KEY (`publishedId`) REFERENCES `test_version` (`id`)) SQL Statement: DELETE FROM `cms`.`test_version` WHERE `id`='17'

Soooooo .....如果cascade = {“remove”}实际上没有删除相关实体(或者那个实体的父实体),有什么意义? < / p>

我可以删除这些记录的唯一方法是,如果我取消设置$ view-&gt; publishId,它会破坏外键关联重叠。

$view = $em->getRepository("GutensiteCmsBundle:View\Test")->find($request->query->get('id'));
$view->setPublishedId(NULL);
$em->persist($view);
$em->flush();
$em->remove($view);
$em->flush();

显然这是由于OneToOne和OneToMany关联之间的重叠造成的。在删除视图之前,我可以忍受在unsetting publishedId的必要性。但我希望专家的反馈能够知道这是否有问题。或建议为这些协会提供更好的解决方案。但是,我有其他记录(如多个路由)指向单个视图实体,因此这就是为什么版本在他们自己的实体上(也是为了保持大量数据在另一个表中进行优化)。所以我的模型似乎很合乎逻辑,例如我想要一个快速简单的方法来引用已发布的版本。我认为单向关系不会造成问题。但它确实......

0 个答案:

没有答案