2

バックグラウンド:

私のアプリケーションには、自己参照 ManyToOne関連を持つエンティティがあります(多くの子が単一の親を指すことができます)。また、Doctrine ORM を使用して一度に多くのエンティティを一括更新する機能があります。多くのエンティティが読み込まれるためにパフォーマンスが劇的に低下するのを防ぐために、エンティティdetachが更新された後に I エンティティを読み込みます。

問題:

私が子供を持っていて後にそれらの子供のいずれかを更新しようとdetachするエンティティが、それがもうを知らないと不平を言うとき。子供を更新しようとする前に親のエンティティであっても。merge

質問:

エンティティをデタッチするときに何が間違っていますか? 親列で cascade="merge" および/または "detach" を実行しようとしましたが、保持しようとすると、Doctrine は親が不明なエンティティであるとまだ不平を言っています。

これを再現する簡単な例をモックアップしました。下記参照。

テストコード:

エンティティ\Thing.php

/**
 * @ORM\Entity()
 * @ORM\Table(name="things")
 */
class Thing
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Thing", inversedBy="children", cascade={"detach","merge"})
     * @ORM\JoinColumn(name="parentId", referencedColumnName="id", onDelete="SET NULL")
     */
    protected $parent;

    /**
     * @ORM\OneToMany(targetEntity="Thing", mappedBy="parent")
     */
    protected $children;

    /**
     * @ORM\Column(type="string", length=64)
     */
    protected $name;

    public function __construct($name = null)
    {
        $this->children = new ArrayCollection();
        $this->name = $name;
    }

    // .. SNIP ...
}

テスト アクション:

public function testThingAction($_route)
{
    $em = $this->getDoctrine()->getEntityManager();
    $repo = $em->getRepository('AcmeThingBundle:Thing');

    // simple setup of a couple things in the DB
    $t1 = $repo->findByName('Thing1');
    if (!$t1) {
        $t1 = new Thing('Thing1');
        $t2 = new Thing('Thing2');
        $t2->setParent($t1);

        $em->persist($t1);
        $em->persist($t2);
        $em->flush();
        return $this->redirect($this->generateUrl($_route));
    }

    list($t1, $t2) = $repo->findAll();

    // detach and re-merge Thing1
    // This should cause Thing1 to be removed and then re-added 
    // to the doctrine's known entities; but it doesn't!?
    $em->detach($t1);
    $em->merge($t1);

    // try to update T2
    $t2->setName('Thing2 - ' . time());
    $em->persist($t2);
    // will fail with: 
    // A new entity was found through the relationship Thing#parent
    $em->flush();

    return array();
}
4

1 に答える 1

1

問題は、Doctrine によって管理されなくなった特定の親オブジェクトとの関係が子にあることです。呼び出す$entityManager->merge($entity)と、その関数から新しいマネージド エンティティが返されます。

それを取り戻したらsetParent()、新しく管理されたエンティティを使用して、各子を手動で呼び出す必要があります。

于 2013-02-13T15:04:53.403 に答える