0

複雑な条件によってこのクエリを制限する問題追跡システムのテーブルで、いくつかの問題をクエリする必要があります。

問題(エンティティ)はカテゴリ(別のエンティティ)にグループ化されます。個人(エンティティ)は複数の役割(4番目のエンティティ)のメンバーであり、これは1つのManyToMany関係です。そして最後に、ロールは1つまたは複数のカテゴリにアクセスできます。これは、2番目のManyToMany関係です。

<?php

/**
 * @Entity
 * @Table(name="issue")
 */
class Issue
{
    /**
     * @ManyToOne(targetEntity="Category", fetch="EAGER")
     * @JoinColumn(name="category", referencedColumnName="id", onDelete="RESTRICT", nullable=false)
     */
    private $category;
    …
}

/**
 * @Entity
 * @Table(name="category")
 */
class Category
{
    /**
     * @ManyToMany(targetEntity="Role", mappedBy="categories")
     */
    private $roles;
    …
}

/**
 * @Entity
 * @Table(name="role")
 */
class Role
{
    /**
     * @ManyToMany(targetEntity="Person", mappedBy="roles")
     */
    private $persons;

    /**
     * @ManyToMany(targetEntity="Category", inversedBy="roles")
     * @JoinTable(name="role_has_access_on_category",
     *  joinColumns={@JoinColumn(name="role_id", referencedColumnName="id")},
     *  inverseJoinColumns={@JoinColumn(name="category_id", referencedColumnName="id")}
     * )
     */
    private $categories;
    …
}

/**
 * @Entity
 * @Table(name="person")
 */
class Person
{   
    /**
     * @ManyToMany(targetEntity="Role", inversedBy="persons")
     * @JoinTable(name="person_is_member_of_role",
     *  joinColumns={@JoinColumn(name="person_id", referencedColumnName="id")},
     *  inverseJoinColumns={@JoinColumn(name="role_id", referencedColumnName="id")})
     */
    private $roles;
    …
}

リレーションシップフィールドを除くすべてのフィールドを残しました。もちろん、主キーとさらに多くの列があります…</ p>

特定の主キーを持つユーザーがメンバーであるロールを介してアクセスできるカテゴリに属する​​すべての問題を取得したいと思います。

最初は、ManyToMany関係を照会する方法を実験し始めたばかりなので、以下のコードは実際には私のターゲットに似ていません。私はついに、クエリを取得して1つのManyToMany関係の反対側を取得する方法を見つけたので、人が属する役割をすでに取得できます。ただし、このクエリは、ロールがアクセスできるカテゴリをフェッチしません。

$qb = $this->em->createQueryBuilder();
$qb->select('person')
   ->addSelect('role')
   ->addSelect('category')
   ->from('Person', 'person')
   ->innerJoin('person.roles', 'role')
   ->innerJoin('role.categories', 'category');

$result = $qb->getQuery()->getResult();

$ resultには、関連するすべての役割を持つ個人データが含まれますが、エンティティではなくカテゴリの空白の配列が含まれます。もちろん、最終的なクエリは問題側から始まりますが、今のところは反対側にのみ進みたいと思います…</ p>

だから今、私はすべての役割を引き受けて、すべてのカテゴリをフェッチするためにそれらをループする必要があるかどうか疑問に思います。より簡単な教義の方法はありませんか?

ちなみに、それは私が使用するSQLです。

SELECT issue.* FROM person AS p, person_is_member_of_role AS pim, role_has_access_on_category AS rha, issue
WHERE
    p.id = pim.person_id AND
    pim.role_id = rha.role_id AND
    rha.category_id = todo.category AND
    p.id = ?;

これですべてが明らかになることを願っています。そうでない場合は、質問を修正します…</ p>

4

1 に答える 1

0

WHEREすべての結合条件を句に入れようとすることで、複雑になりすぎています。

質問を正しく理解した場合、クエリは次のようになります。

SELECT
    i
FROM
    Issue i
JOIN
    i.category c
JOIN
    c.roles r
JOIN
    r.persons p
WHERE
    p.id = :personId

QueryBuilderAPIで翻訳:

$qb = $entityManager->createQueryBuilder();
$issues = $qb
    ->select('i')
    ->from('Issue', 'i')
    ->innerJoin('i.category', 'c')
    ->innerJoin('c.roles', 'r')
    ->innerJoin('r.persons', 'p')
    ->andWhere($qb->expr()->eq('p.id', ':personId'))
    ->setParameter('personId', $personId)
    ->getQuery()
    ->getResult();

QueryBuilderまた、それを使用する正当な理由がない場合は、回避することを検討してください。結局のところ、それは単なる文字列ビルダーです。

于 2013-01-29T02:55:44.490 に答える