使用"自动"策略时,使用Doctrine明确设置Id

Eri*_*ric 94 doctrine doctrine-orm

我的实体使用此注释作为其ID:

/**
 * @orm:Id
 * @orm:Column(type="integer")
 * @orm:GeneratedValue(strategy="AUTO")
 */
protected $id;
Run Code Online (Sandbox Code Playgroud)

在干净的数据库中,我从旧数据库导入现有记录并尝试保留相同的ID.然后,在添加新记录时,我希望MySQL像往常一样自动增加ID列.

不幸的是,Doctrine2似乎完全忽略了指定的ID.


新解决方案

根据以下建议,以下是首选解决方案:

$this->em->persist($entity);

$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
Run Code Online (Sandbox Code Playgroud)

旧解决方案

因为Doctrine偏离ClassMetaData来确定生成器策略,所以在管理EntityManager中的实体之后必须对其进行修改:

$this->em->persist($entity);

$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);

$this->em->flush();
Run Code Online (Sandbox Code Playgroud)

我刚刚在MySQL上对它进行了测试,它按预期工作,这意味着具有自定义ID的实体与该ID一起存储,而没有指定ID的实体使用了lastGeneratedId() + 1.

小智 48

虽然你的解决方案适用于MySQL,但我没能使它与PostgreSQL一起工作,因为它是基于序列的.

我要添加这一行以使其完美运行:

$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());

最好的祝福,

  • 这会永久地设置这台发电机吗?我可以添加一个带有强制ID的记录,然后让它使用自动增量ID吗? (2认同)

Ale*_* B. 28

也许是什么原则改变了,但现在正确的方法是:

$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
Run Code Online (Sandbox Code Playgroud)

  • 这很好用,但你不需要第二行. (5认同)

小智 7

如果实体是类表继承的一部分,则需要更改两个实体的类元数据中的id-generator (您持久存储的实体和根实体)


小智 5

仅当所有实体在插入之前都具有ID时,新解决方案才能正常工作。当一个实体具有ID而另一个实体没有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();
    }
}
Run Code Online (Sandbox Code Playgroud)