1

フラグが立てられた関連するPostエンティティを持つUserエンティティを返す次のクエリがあったとします(これはデモンストレーション用です)。

SELECT u, p
FROM User u
LEFT JOIN u.posts p
WHERE p.isFlagged = true

これを使用したら、isFlaggedに関係なく、そのユーザーのすべての投稿にアクセスしたいと思います。コレクションを更新して$user->posts、すべてのユーザー投稿の完全なコレクションになるようにする簡単な方法はありますか?

クエリ内のすべての投稿を単に引き出したくはありません(必要ない場合があるため)。完全なコレクションを必要とするコードは、このエンティティが由来するクエリを認識しません。

4

3 に答える 3

1

あなたがここでしていることは壊れています:

SELECT
    u, p
FROM
    User u
JOIN
    u.posts p
    WITH
    p.isFlagged = true

これにより、 `User#posts"コレクションが間違った値でハイドレイトされ、ロジックが壊れたり、オブジェクトグラフが壊れたり、すべてが壊れたりします。

次のようなものを使用して、DQLレベルでこれを解決する必要があります。

SELECT
    u, p
FROM
    User u
JOIN
    u.posts p
JOIN
    u.posts j
    WITH
    j.isFlagged = true

これにより、基本的に、中間(壊れた)状態なしで、ユーザーオブジェクト内の正しい投稿コレクションがハイドレイトされます。

編集:私は@Athlanの答えに基づいて考えたので、質問を誤解しました。これは根本的に間違っています(壊れたコレクションをフラッシュするのは本当に間違っています)。これは私の以前の答えであり、問​​題を解決するので興味深いと思いますが、実際には正しい方法ではありません。

この質問は、ORMが期待どおりにコレクションを更新したかどうかを実際に知りたくなりました。

はこのブランチでテストを書きました

基本的に、あなたがする必要があるのは単純です:

$entityManager->refresh($entity);

テストの関連部分は次のとおりです。

$foo = new DDC2666Foo();

$this->_em->persist($foo);
$this->_em->flush();
$this->_em->clear();

$fetchedFoo = $this->_em->find(__NAMESPACE__ . '\DDC2666Foo', $foo->id);

$fetchedFoo->bars->add(new DDC2666Bar());

$this->assertCount(1, $fetchedFoo->bars);
$this->_em->refresh($fetchedFoo);

$this->assertCount(0, $fetchedFoo->bars, 'The collection was reset');

これによってエンティティも再フェッチされるという欠点がありますが、ORM自体は単一のコレクションを更新するためのファサードを提供しません。

とにかく、これも良いことです。この方法では、カプセル化が破られず、コードで予期しない(そしてデバッグが難しい)動作が発生する可能性があります。

于 2013-03-24T16:43:35.383 に答える
0

私はこれと同じ問題を抱えていて、ここに行き着きました。私にはリストがあり、それらの余分なクエリを実行したくないので、更新は私にとってオプションではありません。

ここで本当に必要なのは、フィルタリングを行うために「偽の」結合を追加し、条件なしで元の結合を残すことです...これを明確にするために:

SELECT u, p
FROM User u
LEFT JOIN u.posts p
LEFT JOIN u.posts p2
WHERE p2.isFlagged = true

select句からp2を省略していることに注意してください。これは、フィルタリングの目的のためだけです。

于 2014-06-25T20:26:31.440 に答える
0

他のソリューションは、私がまったく興味を持っていない多くのエンティティがハイドレイトされるため、非常に満足のいくものではないと思います。投稿の大部分がそうである場合isFlagged = 0、パフォーマンスへの影響は甚大です。

これは、エンティティ間の関係を交換することを含む代替ソリューションです。ただし、元の質問が求めていたものと完全に同等ではありません。それでも、この問題を抱えている他の人には役立つかもしれません。

SELECT p, u
FROM Post p
JOIN p.user u
WHERE p.isFlagged = true

このソリューションと他のソリューションの違いは、投稿やフラグ付きの投稿がないユーザーを返さなくなることです。これはあなたが望むものかもしれないし、そうでないかもしれません。

于 2019-06-04T13:05:42.380 に答える