我有一个具有ID的实体:
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
我将数据迁移到此实体,并希望保留现有密钥。我看着" Explicitly set Id with Doctrine when using "AUTO" strategy"并发现我应该能够做到以下几点:
$newData = ... // array containing data to bring in
$newEntity = new MyEntity();
$newEntity->setId($newData['id']);
$newEntity->... // set other data fields
$em->persist($newEntity);
$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$em->flush();
但是,Doctrine没有使用提供的ID。它在插入时忽略它。我也尝试过这种方法,因为有些人似乎很幸运(甚至尝试了两种方法):
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
但这并没有改变任何事情。 ID仍然会自动插入ID。在查询日志中,我看到Doctrine甚至没有尝试插入ID。
如果我从MyEntity注释中删除@ORM\GeneratedValue(strategy="AUTO")
,那么迁移将尊重我提供的ID。但是我想在迁移期间覆盖它。
我正在使用Doctrine 2.4.2。
答案 0 :(得分:1)
要使用此技术,您必须使用以下第二种方法:
$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata = $em->getClassMetadata('CS\AcmeBundle\Entity\MyEntity');
问题是Doctrine会为两者返回相同的类元数据值。 它们都能正确识别类文件,读取它的注释等。显然它们是等价的,除了一个是绝对命名空间而另一个不是。
但是这些字符串将返回getClassMetadata
的不同实例。对一个的更改不会反映在另一个中。如果您希望您的预期技术有效,则必须使用第二种形式,因为这是UnitOfWork
使用的形式。它使用此规范化:
// \Doctrine\ORM\UnitOfWork->getCommitOrder()
...
$className = $this->em->getClassMetadata(get_class($entity))->name;
$class = $this->em->getClassMetadata($className);
...
请注意,在链接问题中,解决方案使用get_class($entity)
。这可能足以获得正确的行为。
更详细:经过大量的代码转换后,我注意到\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory
在其私有属性$loadedMetadata
中记忆了两个版本的类名字符串。用于实际刷新实体的版本是没有前导斜杠的版本,我正在编辑带有前导斜杠的版本。
因为两个字符串都返回相同的数据,所以我认为这代表了实现中的一个错误。
答案 1 :(得分:0)
The differences between GeneratedValue strategies
在您的实体内
替换
@ORM\GeneratedValue(strategy="AUTO")
与
@ORM\GeneratedValue(strategy="NONE")
我不确定您是使用注释还是xml或yml文件。因此,最好还要更改bundle config中的xml或yml doctrine实体文件。