如何使用Doctrine2忽略重复条目?
错误示例:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'symfony' for key 'UNIQ_389B783389B783'
如何使用Doctrine2忽略重复条目?
错误示例:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'symfony' for key 'UNIQ_389B783389B783'
这是Doctrine的一个麻烦之处,它不支持INSERT/UPDATE Ignore,有一些解决方法,比如创建一个方法来检查行是否存在,如果存在,则跳过该行。
您可以捕获异常,以便您的脚本不会因异常而结束。但是,实体管理器将关闭,您将无法再使用它。您仍然可以使用PDO,并且可以在数据库中插入记录,指示批处理失败,因为X
需要重新启动(这通常是我所做的)。
如果以上选项都不适用于您,最终我会编写原始的SQL来进行批处理,根本不使用Doctrine,这样做更快速,而可执行INSERT/UPDATE Ignore使其成为不言而喻的选择。
在 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();
}
composer require symfony/proxy-manager-bridge
- Karol May您可以捕获异常然后忽略它。但请注意,当实体管理器引发异常时,在该请求期间将无法再使用实体管理器。
use Doctrine\Persistence\NotifyPropertyChanged;
use Doctrine\Persistence\PropertyChangedListener;
实现NotifyPropertyChanged类后
class TblPersonPhonePermission implements NotifyPropertyChanged
public function addPropertyChangedListener(PropertyChangedListener $listener)
{
$insertBatch = $listener->getScheduledEntityInsertions();
foreach ($insertBatch as $entity) {
if (
(get_class($entity) === get_class($this)) &&
$this->getId() !== $entity->getId() &&
$this->getPhone() === $entity->getPhone() &&
$this->getChannel() === $entity->getChannel()
) {
$listener->remove($this);
}
}
}
在实际插入之前,您还可以检查重复项。我曾遇到类似的问题,并在此处给出了答案: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();
}
@Unique
索引。 - Anton Babenko