Явно установить идентификатор с доктриной при использовании стратегии "авто"



моя сущность использует эту аннотацию для своего идентификатора:



/**
* @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.

558   7  

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

    Ничего не найдено.