Doctrine2:无法覆盖生成的价值策略?

时间:2014-06-27 14:56:50

标签: symfony doctrine-orm doctrine

我有一个具有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。

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实体文件。