我正在尝试清理一组实体(用关系术语来说就是一个表),这些实体是Color
的实例,我想运行一个使用Doctrine 2删除所有未引用的Color
的脚本。问题是Color
被系统中的许多其他实体引用。所以,我可以想出两个选择:
- 遍历所有颜色,并手动检查每种颜色是否存在对系统上其他实体上特定
Color
的引用,如果没有引用,则将其删除 - 遍历所有颜色并尝试删除其中一种,如果有对该颜色的引用,则捕获由违反完整性约束导致的EM拖掉的异常,因此,我忽略失败的颜色并继续下一个
显然,第二种选择比第一种更简单,所以我试过了。我遇到的问题是,当实体删除失败时,EM会抛出异常,但也会关闭实体管理器,我无法再使用它来删除剩余的颜色!
我在条令2中检查了UnitOfWork
类的commit
方法,事实上。。。
try {
... //Execute queries
$conn->commit();
} catch (Exception $e) {
$this->em->close();
$conn->rollback();
throw $e;
}
有什么方法可以完成我想要做的事情吗(也许重新打开实体经理)
你认为还有更好的方法吗
为什么教义会有这种行为?
还请注意,我正在将条令2与Symfony 2一起使用
理想情况下,您应该在关系中定义orphanRemoval
,这样您就不需要为删除而烦恼。除此之外,我现在可以想出三个解决方案。。
首先,在引用colors
表时,是否在ON DELETE
中使用CASCADE
?
1)
如果你确实使用CASCADE
,我建议按照这里描述的方式实现Doctrine的批处理:批量删除,但这里你的$batchSize
正好是1。
2)
I、 不知何故,将上述解决方案视为效率不高,您也可以通过以下方式实现:
- 遍历引用
Color
实体的实体,并将Color
的id
收集到数组中 - 如果该数组不为空,则执行:
DELETE FROM AcmeDemoBundle:Color c WHERE c.id IN (:ids)
并像往常一样设置ids
参数
3)
如果不使用CASCADE
,还有另一种解决方案。您可以执行原始sql:
DELETE IGNORE FROM color;
在这里,引用的颜色不会被删除,并且会引发错误,但由于IGNORE
,它最终只会作为警告。
希望这些能有所帮助。。。。
类似这样的东西:
// somewhere in ColorRepository.php
$this->createQueryBuilder("o")
->leftJoin("o.Relation1", "r1")
->leftJoin("o.Relation2", "r2)
->where("r1 IS NULL AND r2 IS NULL")
->delete() ;
只有当实体(Color)不再与r1和r2有关系时,才应该加载它们并将其删除。