10

私は Doctrine 2.3 を使用しています。次のクエリがあります。

$em->createQuery('
    SELECT u, c, p
    FROM Entities\User u
    LEFT JOIN u.company c
    LEFT JOIN u.privilege p
    WHERE u.id = :id
')->setParameter('id', $identity)

次に、それを取得し、結果 (配列です。最初の要素を取得するだけです) を取得し、 detach を実行します$em->detach($result);

(Doctrine の APC キャッシュ ドライバーを使用して) キャッシュからフェッチするときは、次のようにします。

$cacheDriver = new \Doctrine\Common\Cache\ApcCache();
if($cacheDriver->contains($cacheId))
{
    $entity = $cacheDriver->fetch($cacheId);
    $em->merge($entity);
    return $entity;
}

そのクエリに表示されているもの以外に、 User オブジェクトに関連付けられている他の多くの関係があるため、これによりエンティティでの関係の読み込みが再度有効になることを願っていました。

私はそのような新しいエンティティを作成しようとしています:

$newEntity = new Entities\ClientType();
$newEntity['param'] = $data;
$newEntitiy['company'] = $this->user['company'];
$em->persist($newEntity);
$em->flush();

これを行うと、エラーが発生します。

A new entity was found through the relationship 'Entities\ClientType#company' that was not configured to cascade persist operations for entity:
Entities\Company@000000005d7b49b500000000dd7ad743. 
To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). 
If you cannot find out which entity causes the problem implement 'Entities\Company#__toString()' to get a clue.

これは、キャッシュから取得したユーザー エンティティの下で会社エンティティを使用しない場合にうまく機能します。新しいエンティティとの関係で使用するたびにデータベースから会社エンティティを再取得する必要がないように、これを機能させる方法はありますか?

編集: これは、これら 2 つの関係を扱う User エンティティにあるものです。

/**
    * @ManyToOne(targetEntity="Company" , inversedBy="user", cascade={"detach", "merge"})
    */
    protected $company;

    /**
    * @ManyToOne(targetEntity="Privilege" , inversedBy="user", cascade={"detach", "merge"})
    */
    protected $privilege;

私はまだ同じエラーが発生しています。

2 番目の編集: a$em->contains($this->user);$em->contains($this->user['company']);両方を試してみると、false が返されます。どちらが聞こえますか...間違っています。

4

1 に答える 1

13

ユーザーをマージするとき、関連する会社と権限もマージする必要がありますよね?

このプロセスはカスケードと呼ばれます。

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations

User エンティティに、 andcascade={"merge"}@ManyToOne注釈 (または使用している別のタイプの関連付け定義) を入れます。$company$privilege

また、detach 呼び出しもカスケードしたい場合は (これをお勧めします) cascade={"detach", "merge"}、.

ps: 1 つの関連付けの両側にそのようなカスケードを配置しないでください。無限ループが作成されます ;)

編集:

このコード片:

$entity = $cacheDriver->fetch($cacheId);
$em->merge($entity);                      // <-
return $entity;

次のようにする必要があります。

$entity = $cacheDriver->fetch($cacheId);
$entity = $em->merge($entity);            // <-
return $entity;

問題は、引数として渡したエンティティをそのままにして、エンティティのマネージド バージョンを表す新しいオブジェクトをmerge()返すことです。したがって、渡した引数ではなく、戻り値を使用する必要があります。

于 2012-11-14T08:35:57.393 に答える