Как игнорировать дубликаты записей с помощью 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, есть обходное решение, например, создание методов, которые проверяют, существует ли строка, и если это так, просто пропустите ее.
Вы можете поймать исключение, так что ваш script не закончится исключением. Однако диспетчер объектов будет закрыт, и вы больше не сможете его использовать. Тем не менее, вы все равно можете использовать PDO, и вы можете вставить запись в базу данных, указывающую на то, что ваша партия завершилась неудачно, поскольку X
и ее необходимо перезапустить (что я обычно делаю).
Если ни одна из вышеперечисленных опций не работает для вас, в конечном итоге я в конечном итоге пишу raw SQL для пакетной обработки, и я вообще не использую Doctrine, она заканчивается быстрее и способность делать INSERT/UPDATE Ignore делает это без проблем.
В Symfony 3 вы можете reset manager и продолжить работу с ним, вызвав метод 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();
}
Вы всегда можете поймать исключение, а затем проигнорировать его. Просто имейте в виду, что когда администратор сущности создает исключение, диспетчер объектов больше не может использоваться во время этого запроса.
Вы также можете проверить наличие дубликатов перед фактической вставкой. У меня была похожая проблема, и я ответил на нее здесь: doctrine/symfony 4 - избегайте повторяющихся записей при сохранении дочерних сущностей
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();
}