使用Doctrine 2检查完整性约束违规

时间:2012-10-10 19:22:19

标签: php symfony doctrine-orm

我正在尝试清理一组实体(即一个表,在关系术语中),这些实体是Color的实例,我想运行一个使用Doctrine 2删除的脚本所有未引用的Color。问题是系统中的许多其他实体引用了Color。所以,我可以想到两个选择:

  1. 迭代所有颜色并手动检查每个颜色是否存在对我系统上其他实体的特定Color的引用,如果没有引用,则删除它。
  2. 迭代所有颜色并尝试删除一个颜色,并且,如果存在对该颜色的引用,则捕获由完整性约束违规导致的EM抛出的异常,因此,我确实忽略失败的颜色并继续下一个。 / LI>

    显然,第二种选择比第一种更简单,所以我试过了。我遇到的问题是,当一个实体删除失败时,EM抛出一个异常,但也关闭了实体管理器,我不能再用它来删除剩余的颜色了!

    我在Doctrine 2中检查commit类的UnitOfWork方法,实际上......

    try {
        ... //Execute queries
    
        $conn->commit();
    } catch (Exception $e) {
        $this->em->close();
        $conn->rollback();
    
        throw $e;
    }
    

    有没有办法完成我想要做的事情(也许重新开放实体经理)? 你相信有更好的方法吗?
    为什么Doctrine有这种行为?

    另请注意我在Symfony 2中使用Doctrine 2

2 个答案:

答案 0 :(得分:1)

理想情况下,您可以在关系中定义orphanRemoval,这样您就不必费心去除。除此之外,我现在可以想到3个解决方案..

首先,在引用CASCADE表时,您是否在ON DELETE中使用colors

1)

如果您确实使用CASCADE,我建议您按照此处所述的方式实施Doctrine的批处理:BULK DELETE但此处您的$batchSize恰好是1。

2)

我,不知何故,看到上述解决方案效率不高,你也可以通过以下方式实现:

  • 浏览引用Color实体的实体,并将id Color收集到数组中。
  • 如果该数组不为空,请执行:DELETE FROM AcmeDemoBundle:Color c WHERE c.id IN (:ids)并照常设置ids参数。

3)

如果使用CASCADE,还有另一种解决方案。您可以执行原始SQL

DELETE IGNORE FROM color;

此处,引用的颜色不会被删除,并会触发错误,但由于IGNORE,它最终只会作为警告。

希望其中一些有帮助......

答案 1 :(得分:0)

这样的事情:

// somewhere in ColorRepository.php

$this->createQueryBuilder("o")
    ->leftJoin("o.Relation1", "r1")
    ->leftJoin("o.Relation2", "r2)
    ->where("r1 IS NULL AND r2 IS NULL")
    ->delete() ;

只有当它们与r1和r2没有关系并删除它们时才会加载你的实体(Color)。