我在我的symfony包中使用yml-syntax创建了一个实体,位于Resources / config / doctrine文件夹中:
Sulu\Bundle\TranslateBundle\Entity\Translation:
type: entity
table: tr_translations
id:
code:
type: string
column: idCodes
associationKey: id
catalogue:
type: string
column: idCatalogues
associationKey: id
fields:
value:
type: text
manyToOne:
code:
targetEntity: Code
inversedBy: tr_codes
joinColumn:
name: idCodes
referencedColumnName: id
catalogue:
targetEntity: Catalogue
inversedBy: tr_catalogues
joinColumn:
name: idCatalogues
referencedColumnName: id
这部分工作正常。但是,当我创建一些像下面的代码中的对象时,我得到一条错误消息,我必须使用flush方法,以获取外键的ID。
这是我目前使用的代码段:
// create a new package and catalogue for the import
$package = new Package();
$package->setName($this->getName());
$catalogue = new Catalogue();
$catalogue->setLocale($this->getLocale());
$catalogue->setPackage($package);
$this->em->persist($package);
$this->em->persist($catalogue);
// load the file, and create a new code/translation combination for every message
$fileCatalogue = $loader->load($this->getFile(), $this->getLocale());
foreach ($fileCatalogue->all()['messages'] as $key => $message) {
$code = new Code();
$code->setPackage($package);
$code->setCode($key);
$code->setBackend(true);
$code->setFrontend(true);
$translate = new Translation();
$translate->setCode($code);
$translate->setValue($message);
$translate->setCatalogue($catalogue);
$this->em->persist($code);
$this->em->flush(); //FIXME no flush in between, if possible
$this->em->persist($translate);
}
// save all the changes to the database
$this->em->flush();
如果我没有在foreach循环中调用flush,我会收到以下错误,我完全理解,但是对于这个问题,是不是有更优雅的解决方案?
Doctrine \ ORM \ ORMException:类型的实体 Sulu \ Bundle \ TranslateBundle \ Entity \ Translation有一个身份通过 外国实体Sulu \ Bundle \ TranslateBundle \ Entity \ Code,但是这个 实体本身没有身份。你必须打电话 EntityManager#persist()在相关实体上并确保一个 在尝试持久化之前生成了标识符 '苏鲁\包\ TranslateBundle \实体\翻译'。如果是邮政 插入ID生成(例如MySQL自动增量或PostgreSQL SERIAL)这意味着你必须在两者之间调用EntityManager #flush() 坚持不懈的行动。
答案 0 :(得分:4)
不幸的是,根据Doctrine Docs,您必须调用flush来获取外键的ID:
保证生成的实体标识符/主键 在下一次成功的冲洗操作之后可以使用 有问题的实体。您不能依赖生成的标识符 在调用persist后直接可用。反之亦然。 您不能依赖生成的标识符在a之后不可用 刷新操作失败。
答案 1 :(得分:0)
您是否尝试过以下内容?
YAML:
Sulu\Bundle\TranslateBundle\Entity\Translation:
type: entity
table: tr_translations
id:
code:
type: string
column: idCodes
associationKey: id
catalogue:
type: string
column: idCatalogues
associationKey: id
fields:
value:
type: text
manyToOne:
code:
targetEntity: Code
cascade: ["persist"]
inversedBy: tr_codes
joinColumn:
name: idCodes
referencedColumnName: id
catalogue:
targetEntity: Catalogue
cascade: ["persist"]
inversedBy: tr_catalogues
joinColumn:
name: idCatalogues
referencedColumnName: id
在你的班级翻译
public function __construct()
{
$this->code = new \Doctrine\Common\Collections\ArrayCollection();
$this->catalogue = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addCatalogue($catalogue)
{
$this->catalogue[] = $catalogue;
return $this;
}
public function addCode($code)
{
$this->code[] = $code;
return $this;
}
那么您的代码可以是这样的:
$package = new Package();
$package->setName($this->getName());
$catalogue = new Catalogue();
$catalogue->setLocale($this->getLocale())->setPackage($package);
$fileCatalogue = $loader->load($this->getFile(), $this->getLocale());
foreach ($fileCatalogue->all()['messages'] as $key => $message) {
$code = new Code();
$code->setPackage($package)
->setCode($key)
->setBackend(true)
->setFrontend(true);
$translate = new Translation();
$translate->addCode($code)
->setValue($message)
->addCatalogue($catalogue);
$this->em->persist($translate);
}
$this->em->flush();
注意: cascade:[“persist”] - Cascades将操作持久保存到关联实体。 Link