0

我需要在问题跟踪系统的表中查询一些问题,通过一个复杂的条件限制此查询:

问题(实体)被分组为类别(另一个实体)。人员(实体)是多个角色(第四个实体)的成员,这是一种多对多关系。最后,一个角色可以访问一个或多个类别,这是第二个 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>

我想检索属于具有给定主键的人可以通过其所属角色访问的类别的所有问题。

一开始我只是开始试验如何查询多对多关系,所以下面的代码与我的目标并不真正相似。我终于找到了如何获取查询以检索一个多对多关系的另一端,因此我已经可以获取一个人所属的角色。但是此查询不会获取角色有权访问的类别。

$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 回答