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

Joh*_*ann 3 join left-join symfony doctrine-orm

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

Company <-> Department <-> DepartmentEmployee <-> Employee
Run Code Online (Sandbox Code Playgroud)

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

// 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();
}
Run Code Online (Sandbox Code Playgroud)

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

当我删除该部分

->leftJoin('r.employee', 'e')
->addSelect('e')
Run Code Online (Sandbox Code Playgroud)

我只得到一个像预期执行的查询.

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

Joh*_*ann 9

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

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

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

为了解决这个问题,目前必须执行查询以找出该信息.

链接

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

$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();
Run Code Online (Sandbox Code Playgroud)