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

Posted

技术标签:

【中文标题】在 Doctrine2/Symfony2 中的重复条目上插入忽略【英文标题】:insert ignore on duplicate entries in Doctrine2/Symfony2 【发布时间】:2012-03-14 09:58:12 【问题描述】:

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

错误示例:

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

【问题讨论】:

你可以做 propel 做的事情:创建一个像 findByKeyOrCreate() 这样的方法,如果有则返回一个现有实体,如果没有则创建一个新实体。 如果不需要,请从该字段中删除 @Unique 索引。 当您尝试保存非唯一条目时,您期望从中得到什么结果? 【参考方案1】:

这是 Doctrine 的麻烦之一,无法执行 INSERT/UPDATE Ignore,有一些解决方法,例如创建一个方法来检查该行是否存在,如果存在则跳过它。

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

如果以上选项都不适合您,最终我会编写原始 SQL 来进行批处理,而我根本不使用 Doctrine,它最终会更快,并且执行 INSERT/UPDATE Ignore 的能力使它成为可能不费吹灰之力。

【讨论】:

如果你不介意覆盖项目,你可以使用 ***.com/a/15838232/1454173 中的合并(已弃用,将在 Doctrine ORM 3.0 中删除)【参考方案2】:

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

这是一个例子:

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();

【讨论】:

不错的分享! (即resetManager()) 我会对这种类型的最新答案感兴趣。 resetManager() 现已弃用。 如果你使用 symfony 3/4 使用composer require symfony/proxy-manager-bridge【参考方案3】:

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

【讨论】:

【参考方案4】:

您还可以在实际插入之前检查重复项。我有一个类似的问题并在这里回答: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();

【讨论】:

这仅在您将重复项保存在一个线程中时有用,这是更简单的情况。问题通常是两个线程(两个服务器请求)试图同时创建相同的东西。

以上是关于在 Doctrine2/Symfony2 中的重复条目上插入忽略的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Doctrine2 (Symfony2) 中按案例排序

Doctrine 2,Symfony 2 中的独特约束

js 中如何去掉数组中的重复的数据

如何在android中删除arraylist中的重复名称[重复]

如何删除已经在list中的重复项

仅消除某些列中的重复行,将所有列保留在 R [重复]