Явно установить идентификатор с доктриной при использовании стратегии "авто"
моя сущность использует эту аннотацию для своего идентификатора:
/**
* @orm:Id
* @orm:Column(type="integer")
* @orm:GeneratedValue(strategy="AUTO")
*/
protected $id;
из чистой базы данных я импортирую существующие записи из старой базы данных и пытаюсь сохранить те же идентификаторы. Затем, при добавлении новых записей, я хочу, чтобы MySQL автоматически увеличивал столбец ID, как обычно.
к сожалению, похоже, что Doctrine2 полностью игнорирует указанный идентификатор.
Новое Решение
согласно приведенным ниже рекомендациям, следующее предпочтительное решение:
$this->em->persist($entity);
$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGeneratorType(DoctrineORMMappingClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new DoctrineORMIdAssignedGenerator());
Старое Решение
поскольку доктрина поворачивается от ClassMetaData для определения стратегии генератора, она должна быть изменена после Управления сущностью в EntityManager:
$this->em->persist($entity);
$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGeneratorType(DoctrineORMMappingClassMetadata::GENERATOR_TYPE_NONE);
$this->em->flush();
Я только что проверил это на MySQL, и он работал, как ожидалось, то есть сущности с пользовательским идентификатором хранились с этим идентификатором, в то время как те, у кого нет указанного идентификатора, использовали lastGeneratedId() + 1.
7 ответов:
хотя ваше решение отлично работает с MySQL, я не смог заставить его работать с PostgreSQL, поскольку он основан на последовательности.
Я должен добавить эту строку, чтобы она работала отлично:
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());С уважением,
возможно, что доктрина изменилась, но теперь правильный путь:
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
в случае, если объект является частью класс таблица наследования вам нужно изменить id-генератор в метаданных класса для и сущности (сущность, которую вы сохраняете, и корневая сущность)
новое решение отлично работает только тогда, когда все объекты имеют идентификатор перед вставкой. Когда один объект имеет идентификатор, а другой нет - новое решение не работает.
Я использую эту функцию для импорта все мои данные:
function createEntity(\Doctrine\ORM\EntityManager $em, $entity, $id = null) { $className = get_class($entity); if ($id) { $idRef = new \ReflectionProperty($className, "id"); $idRef->setAccessible(true); $idRef->setValue($entity, $id); $metadata = $em->getClassMetadata($className); /** @var \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata */ $generator = $metadata->idGenerator; $generatorType = $metadata->generatorType; $metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator()); $metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE); $unitOfWork = $em->getUnitOfWork(); $persistersRef = new \ReflectionProperty($unitOfWork, "persisters"); $persistersRef->setAccessible(true); $persisters = $persistersRef->getValue($unitOfWork); unset($persisters[$className]); $persistersRef->setValue($unitOfWork, $persisters); $em->persist($entity); $em->flush(); $idRef->setAccessible(false); $metadata->setIdGenerator($generator); $metadata->setIdGeneratorType($generatorType); $persisters = $persistersRef->getValue($unitOfWork); unset($persisters[$className]); $persistersRef->setValue($unitOfWork, $persisters); $persistersRef->setAccessible(false); } else { $em->persist($entity); $em->flush(); } }
решение для доктрины 2.5 и MySQL
"новое решение" не работает с доктриной 2.5 и MySQL. Вы должны использовать:
$metadata = $this->getEntityManager()->getClassMetaData(Entity::class); $metadata->setIdGenerator(new AssignedGenerator()); $metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);однако я могу только подтвердить это для MySQL, потому что я еще не пробовал никаких других СУБД.
Я создал библиотека чтобы установить будущие идентификаторы для объектов доктрины. Он возвращается к исходной стратегии генерации идентификаторов, когда все идентификаторы в очереди используются для минимизации воздействия. Это должно быть легкое падение для модульных тестов, чтобы такой код не нужно было повторять.
вдохновленный Villermen работа, я создал это библиотека что позволяет вручную назначать идентификаторы сущности доктрины, даже если сущность использует stategies AUTO, SEQUENCE, IDENTITY или UUID.
вы не должны использовать его в производстве.
библиотека автоматически определит объекты с присвоенным идентификатором и заменит генератор только при необходимости. Библиотека будет отступать на начальном генераторе, когда экземпляр не имеет идентификатор.
замена генератора происходит в EventListener доктрины, никакая потребность добавить любой дополнительный код в ваших приспособлениях.
Comments