3

我在 Resources/config/doctrine 文件夹中的 symfony 包中使用 yml-syntax 创建了一个实体:

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 循环中调用刷新,我会收到以下错误,我完全理解,但是对于这个问题没有更优雅的解决方案吗?

Doctrine\ORM\ORMException : Sulu\Bundle\TranslateBundle\Entity\Translation 类型的实体通过外部实体 Sulu\Bundle\TranslateBundle\Entity\Code 具有身份,但是该实体本身没有身份。您必须在相关实体上调用 EntityManager#persist() 并确保在尝试持久化“Sulu\Bundle\TranslateBundle\Entity\Translation”之前生成了一个标识符。在 Post Insert ID Generation(例如 MySQL Auto-Increment 或 PostgreSQL SERIAL)的情况下,这意味着您必须在两个持久化操作之间调用 EntityManager#flush()。

4

2 回答 2

4

不幸的是,根据Doctrine Docs,您必须调用 flush 来获取外键的 ID:

生成的实体标识符/主键保证在涉及相关实体的下一次成功刷新操作后可用。在调用 persist 后,您不能依赖生成的标识符直接可用。反之亦然。在刷新操作失败后,您不能依赖生成的标识符不可用。

于 2013-08-13T09:24:22.593 回答
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();

注意:级联:[“persist”] - 级联将操作持久化到关联实体。关联

于 2013-08-12T16:29:47.343 回答