Doctrine 2发出不需要的查询,或者我错了,这是必要的吗?

时间:2013-09-07 13:35:32

标签: mysql doctrine-orm doctrine inner-join

我的学说实体Section具有自引用关联parentslug属性。我创建了这个函数(在部分存储库中),用于返回给定其web路径的部分:

/**
 * Finds a section by its path, i.e. /a/b/c.
 *
 * @param string $path
 * @return null|\Application\Entity\Section
 */
public function findOneByPath($path)
{
    // Slug exploding so we get array("a", "b", "c")
    if (!($slugs = explode('/', $path))) {
        return null;
    }

    // Get the slug for the leaf (at least) i.e. "c"
    $leafSlug = array_pop($slugs);

    // Query builder for selecting the leaf
    $qb = $this->createQueryBuilder('s0');
    $qb->select('s0')
        ->where($qb->expr()->eq('s0.slug', ':s0_slug'))
        ->setParameter('s0_slug', $leafSlug);

    // Dynamical adding joins in reverse order i.e. array("b", "a")
    $idx = 0;
    foreach (array_reverse($slugs) as $slug) {
        $qb->innerJoin("s{$idx}.parent", "s".++$idx)
            ->andWhere($qb->expr()->eq("s{$idx}.slug", ":s{$idx}_slug"))
            ->setParameter("s{$idx}_slug", $slug);
    }

    return $qb->getQuery()->getOneOrNullResult();
}

它工作正常,但我无法理解为什么 Doctrine正在进行两次查询(日志文件):

[2013-09-07 15:26:30] App.DEBUG: SELECT s0_.id AS id0, s0_.slug AS slug1 [...]
FROM section s0_ INNER JOIN section s1_ ON s0_.parent_id = s1_.id
WHERE (s0_.slug = ? AND s1_.slug = ?) ["b","a"] []

[2013-09-07 15:26:30] App.DEBUG: SELECT t0.id AS id1, t0.slug AS slug2 [...]
FROM section t0 WHERE t0.id = ? ["1"] []

正如你所看到的那样,第一个是INNER JOIN并且它是正确的。第二个是没用的,我想......或者我错过了什么?顺便说一下,1是“a”的id ...

编辑:当foreach未执行时(即findOneByPath('a')),这种情况不会发生。有n + 1次查询(n不需要的)作为foreach次迭代次数(/a/b/c/d次4次查询)。

1 个答案:

答案 0 :(得分:1)

在foreach中,您正在加入更多表,但是您没有将它们添加到SELECT子句中,这会导致N + 1查询情况。你需要在foreach中添加这样的东西:

$qb->addSelect('s' . $idx);