在Doctrine2 / Symfony2中的重复条目上插入ignore

时间:2012-03-14 09:58:12

标签: doctrine symfony doctrine-orm

如何使用Doctrine2忽略重复的条目?

错误示例:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'symfony' for key 'UNIQ_389B783389B783'

4 个答案:

答案 0 :(得分:14)

Symfony 3 中,您可以重置管理员,并在捕获resetManager()例外后通过调用Doctrine对象的UniqueConstraintViolationException方法继续使用它。

以下是一个例子:

try {
  $em = $this->getDoctrine()->getManager();
  $entity = Product::create()
    ->setTitle('Some title')
    ->setUrl('http://google.com');
  $em->persist($entity);
  $em->flush();
}
catch (UniqueConstraintViolationException $e) {
  $this->getDoctrine()->resetManager();
}

答案 1 :(得分:13)

这是Doctrine的一个麻烦,它无法进行INSERT / UPDATE忽略,有一些解决方法,比如创建一个检查行是否存在的方法,如果确实存在,那么就跳过它。

您可以捕获异常,以便您的脚本不会以异常结束。但是,实体经理将被关闭,您将无法再使用它。您仍然可以使用PDO,但是您可以在数据库中插入一条记录,指示您的批处理失败,因为X并且需要重新启动(这是我通常所做的)。

如果上面的选项都不适合你,最终我最终编写原始SQL来进行批处理,而我根本不使用Doctrine,它最终会更快,并且能够执行INSERT / UPDATE忽略让它变得毫无疑问。

答案 2 :(得分:11)

您始终可以捕获异常,然后忽略它。请注意,当实体管理器引发异常时,在该请求期间不能再使用实体管理器。

答案 3 :(得分:0)

您还可以在实际插入之前检查重复项。我有一个类似的问题,并在这里回答:doctrine/symfony 4 - avoid duplicate entry when persisting child entities

protected function removeDuplicates($insertions) {
    foreach ($insertions as $key => $insertion) {
        $shortClassName = (new ReflectionClass($insertion))->getShortName();
        // TODO: The search can be heavily optimized
        foreach ($insertions as $possibleDupeKey => $possibleDupeInsertion) {
            $shortDupeClassName = (new ReflectionClass($insertion))->getShortName();
            // TODO: Treat case when unique is on a field not called 'id'
            if ($shortClassName === $shortDupeClassName && $insertion->getId() === $possibleDupeInsertion->getId() && $key !== $possibleDupeKey) {
                $this->em->remove($possibleDupeInsertion);
            }
        }
    }
}

protected function saveStuff($order) {
    $this->em->persist($order);
    $this->removeDuplicates($this->em->getUnitOfWork()->getScheduledEntityInsertions());
    $this->em->flush();
}