使用“自动”策略时,显式设置标识与教条
我的实体使用这个注解为它的ID:
/** * @orm:Id * @orm:Column(type="integer") * @orm:GeneratedValue(strategy="AUTO") */ protected $id;
从一个干净的数据库,我从旧的数据库现有的logging导入,并试图保持相同的ID。 然后,当添加新logging时,我希望MySQL像往常一样自动增加ID列。
不幸的是,似乎Doctrine2完全忽略了指定的ID。
新解决scheme
根据以下build议,以下是首选解决scheme:
$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());
旧解决scheme
由于Doctrineclosures了ClassMetaData以确定生成器策略,因此必须在pipe理EntityManager中的实体后对其进行修改:
$this->em->persist($entity); $metadata = $this->em->getClassMetaData(get_class($entity)); $metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE); $this->em->flush();
我只是在MySQL上进行了testing,并且按照预期工作,这意味着具有自定义ID的实体与该ID一起存储,而没有指定ID的lastGeneratedId() + 1
使用lastGeneratedId() + 1
。
虽然你的解决scheme在MySQL中工作的很好,但是我没有使它和PostgreSQL一起工作,因为它是基于序列的。
我要添加这条线,使其完美的工作:
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
最好的祝福,
也许什么学说改变了,但现在正确的方法是:
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE); $metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
如果实体是类表inheritance的一部分,则需要更改两个实体(您所持有的实体和根实体)的类元数据中的ID生成器,
新的解决scheme只有在插入前所有实体都有id时才能正常工作 当一个实体有身份证,另一个实体没有 – 新的解决scheme失败。
我用这个函数导入我所有的数据:
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(); } }
Doctrine 2.5和MySQL的解决scheme
“新解决scheme”不适用于Doctrine 2.5和MySQL。 你必须使用:
$metadata = $this->getEntityManager()->getClassMetaData(Entity::class); $metadata->setIdGenerator(new AssignedGenerator()); $metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
但是我只能确认对于MySQL,因为我还没有尝试过任何其他的DBMS。