如何在使用内部Join时优化Doctrine查询的数量


How to optimize number of Doctrine queries when using an inner Join?

我必须简单的实体:日志和用户。日志与实体具有ManyToOne关系。

Log:
  type: entity
  repositoryClass: LogRepository
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    message:
      type: string      
  manyToOne:
    user:
      targetEntity: User
      joinColumns:
        user_id:
          referencedColumnName: id

我的用例是显示日志列表和一两个关于用户的信息(比如他的名字和邮件)

如果我使用findall方法,Symfony调试工具栏会显示Doctrine执行大量查询。一个查询给我日志,每个用户执行一个查询!这当然不好,因为我可以看到一千根原木。我不想让我的数据库服务器过载。这个问题似乎很容易解决。但我搜索了一段时间,结果似乎是"糟糕的做法"。

因此,我开始在LogRepository类中使用querybuilder:编写一个新方法

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l')
            ->innerJoin(
                'ApplicationSonataUserBundle:User', 'u', 
                Expr'Join::WITH,'l.user = u.id')
        ;
        return $qb->getQuery()->getResult();
}

我仍然有同样的问题。我已将方法上的选择参数更改为:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l','u')
            ->innerJoin('ApplicationSonataUserBundle:User','u', 
                        Expr'Join::WITH,'l.user = u.id')
        ;
        return $qb->getQuery()->getResult();
}

尤里卡?好吧,我只有一个查询,但我的方法并没有只返回Log,而是返回User。。。所以我的Twig模板崩溃了,因为我的循环包含User,而不仅仅是Log。当这是一个用户时,我的视图会崩溃,因为我想写消息字段。(Log.message存在。但User.message当然不是有效字段)

如果我再改变一次我的方法,用一个循环来过滤我的结果,它的效果非常好:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l','u')
            ->innerJoin('ApplicationSonataUserBundle:User','u',
                        Expr'Join::WITH,'l.user = u.id')
        ;
        //THE STRANGE LOOP
        $results = array();
        foreach ($qb->getQuery()->getResult() as $result){
            if ($result instanceof Log){
                $results[] = $result;
            }
        };
        return $results;
}

我只有一个查询,那就是我正在搜索的内容。我的小树枝模板不会崩溃,因为我的数组只包含Log。

那怎么了?它是有效的,但我认为这不是好的/最佳的做法。

有人可以向我解释一种更好的方法,一种使用内部联接查询的更好实践,以最小化执行的查询,并获得只包含Log实例的ArrayCollection结果?

应该没有必要使用循环。尝试如下:

public function getLog(){
    $qb = $this->createQueryBuilder('l')
        ->select('l','u')
        ->innerJoin('l.user', 'u');
    $logs = $qb->getQuery()->getResult();
    return $logs;
}

它应该只返回具有已填充(fetch joined)的关联用户的$logs