Doctrine2:无法重写生成的价值战略? [英] Doctrine2: Unable to override generated value strategy?

查看:125
本文介绍了Doctrine2:无法重写生成的价值战略?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个身份证号码的实体:

  / ** 
* @ ORM\列(type =integer)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =AUTO)
* /
protected $ id;

我正在将数据迁移到此实体,并希望保留现有的密钥。我看着在使用自动时明确地设置Id与原则;策略,发现我应该能够执行以下操作:

  $ newData = ... / /数组包含数据带来

$ newEntity = new MyEntity();
$ newEntity-> setId($ newData ['id']);
$ newEntity-> ... //设置其他数据字段

$ 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仍然由数据库自动插入。在查询日志中,我看到Doctrine甚至没有尝试插入ID。



如果我删除 @ ORM\GeneratedValue(策略=AUTO)从MyEntity注释,然后迁移将尊重提供的ID给予它。但是我想在迁移期间重写它。



我使用的是Doctrine 2.4.2。

  $元数据= $ 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($实体)。这可能足以获得正确的行为。






更多细节:经过大量的代码之后,我注意到 \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory 正在其私有属性 $ loadedMetadata中记录类名字符串的两个版本。用于实际冲洗实体的版本是没有主导斜杠的版本,我正在用主要的斜杠编辑它。



由于这两个字符串都返回相同的数据,我认为这代表了实现中的一个错误。


I have a an entity with an ID as such:

/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

I'm migrating data into this entity, and want to preserve existing keys. I looked at "Explicitly set Id with Doctrine when using "AUTO" strategy" and found that I should be able to do the following:

$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();

However, Doctrine is not using the provided ID. It's ignoring it when inserting. I've also tried this approach instead, since some people seemed to have had luck with it (even tried both):

$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);

But that doesn't change anything. ID's are still inserted automatically by the database. In the query log, I see that Doctrine isn't even attempting to insert the ID.

If I remove @ORM\GeneratedValue(strategy="AUTO") from MyEntity annotations, then the migration will respect the provided ID I give it. But I want to override it just during the migration.

I'm using Doctrine 2.4.2.

解决方案

For this technique to work, you must use the second of these:

$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata = $em->getClassMetadata('CS\AcmeBundle\Entity\MyEntity');

The problem is that Doctrine will return the same class meta data values for both. They will both correctly identify the class file, read its annotations, etc. Obviously they are equivalent, except that one is an absolute namespace and the other is not.

But these strings will return different instances from getClassMetadata. Changes to one won't reflect in the other. If you want your intended technique to work, you must use the second form, because that is what UnitOfWork uses. It uses this normalization:

// \Doctrine\ORM\UnitOfWork->getCommitOrder()
...
$className = $this->em->getClassMetadata(get_class($entity))->name;
$class = $this->em->getClassMetadata($className);
...

Note that in the linked-to question, the solution uses get_class($entity). That is probably sufficient to get the correct behavior.


Even more detail: after a lot of stepping through code, I noticed that \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory was memoizing both versions of the class name string in its private property $loadedMetadata. The version that was being used to actually flush the entities was the one without the leading slash, and I was editing the one with the leading slash.

Because both strings return the same data, I think this represents a bug in the implementation.

这篇关于Doctrine2:无法重写生成的价值战略?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆