Doctrine2在多个级别上连接多个请求

时间:2014-03-15 19:05:40

标签: symfony join doctrine-orm left-join

我有4个与层级相关的实体:CompanyDepartmentEmployeeCompanyDepartment与ManyToOne双向关系相关。 DepartmentEmployee通过具有2个OneToMany双向关系的另一个实体相关,因为我需要关系的其他参数。所以基本上最终的架构是这样的:

Company <-> Department <-> DepartmentEmployee <-> Employee

我试图从当前用户的公司中选择一个部门,并获得该部门的所有员工。我使用自定义存储库使用查询构建器构建我的查询,如下所示:

// DepartmentRepository.php

public function getOneWithEmployees($slug, $company)
{
    $qb = $this->createQueryBuilder('d')
            ->where('d.slug = :slug')
            ->andWhere('c.slug = :company')
            ->setParameters(array('slug' => $slug, 'company' => $company))
        ->leftJoin('d.company', 'c')
        ->addSelect('c')
        ->leftJoin('d.departmentEmployee', 'r')
        ->addSelect('r')
        ->leftJoin('r.employee', 'e')
        ->addSelect('e');

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

重点是减少查询次数,但是当我执行此查询时,我仍然会对数据库进行32次查询(我在该部门有15名员工)。

当我删除部分时

->leftJoin('r.employee', 'e')
->addSelect('e')

我只按预期执行一个查询。

如何在不触发多重查询的情况下在左连接上执行左连接?

1 个答案:

答案 0 :(得分:9)

我的Employee实体是2个OneToOne关系的反面:UserInvitation。当我使用left join在查询中明确包含这些关系时,不会进行额外的查询,但是如果我将它们排除在外,那么Doc​​trine会自动进行查询以获取它们。查看Doctrine FAQ我发现了这个:

  

4.7.1。为什么每次获取具有一对一关系的实体时都会执行额外的SQL查询?

     

如果Doctrine检测到您正在获取反向一对一关联,则必须执行另一个查询才能加载此对象,因为它无法知道是否没有此类对象(设置为null)或是否应该设置代理和此代理具有的ID。

     

要解决此问题,目前必须执行查询才能找到此信息。

Link

因此避免额外查询的唯一解决方案是构建我的查询:

$qb = $this->createQueryBuilder('d')
        ->where('d.slug = :slug')
        ->andWhere('c.slug = :company')
        ->setParameters(array('slug' => $slug, 'company' => $company))
    ->leftJoin('d.company', 'c')
    ->addSelect('c')
    ->leftJoin('d.departmentEmployee', 'r')
    ->addSelect('r')
    ->leftJoin('r.employee', 'e')
    ->addSelect('e')
    ->leftJoin('e.user', 'u')
    ->addSelect('u')
    ->leftJoin('e.invitation', 'i')
    ->addSelect('i');

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