【问题标题】:Doctrine related entities additional queries教义相关实体附加查询
【发布时间】:2016-01-22 20:38:15
【问题描述】:

我有点困惑为什么 Doctrine 查询以这种特定方式工作。假设我们有 Articles 和 Users 实体,Users 与 Articles 具有 OneToMany 关系。

然后,在控制器中,我们将获取所有文章并将它们发送到视图。

$em = $this->getEntityManager();    
$articles = $em->getRepository('MyBundle:Article')->findAll();

在视图中我们会循环它们。

{% for article in articles %}
    {{ article.author.name }}
{% endfor %}

这里的问题是这段代码对每一篇文章都做了一个额外的查询(针对文章的用户)。

我知道我们可以使用 DQL,但我的问题是 Doctrine 在这里是如何工作的,为什么它不针对这种很常见的事情进行优化?我发现这是应用程序中常用的“错误”,这确实会减慢它们的速度。我刚刚发现了这一点,现在我必须将这么多查询重写到我的控制器中。

这也违背了 ORM 的目的,它实际上应该提供编写应用程序的速度。这迫使我们编写 DQL/QB 查询而不是利用 ORM。那么,如果 ORM 表现如此糟糕,什么时候使用它是个好主意?

【问题讨论】:

  • 查看 eager 和 lazy fetching,你就会开始明白了。
  • Eager fetch 的问题是它总是会获取相关实体,即使它们不需要。
  • @GeorgeIrimiciuc 这就是权衡。要么您总是获取相关实体以预期对其进行迭代,要么您不这样做,并且在需要时检索它们。 ORM 自己无法知道您将如何使用相关实体,您需要告诉它。
  • 但是当我调用相关实体时,它为什么不在视图中创建查询?为什么要创建单独的查询?

标签: php symfony doctrine-orm


【解决方案1】:

我知道我们可以使用 DQL,但我的问题是 Doctrine 在这里是如何工作的,为什么不针对这种很常见的事情进行优化?

Doctrine 无法猜测您在 Twig 视图中需要什么值。

但是当我调用相关实体时,为什么它不在视图中创建查询?为什么要创建单独的查询?

这不可能是解决方案。代码见:

{% for article in articles %}
    {{ article.author.name }}
{% endfor %}

要知道你必须显示什么值,Symfony 应该遍历循环以猜测你需要什么值,这在获取数据之前会做很多工作。


您可以明确告诉 Doctrine 应该将哪些表关联添加到查询中:

ArticleRepositoryrepository,你要join相关表:

<?php

namespace Acme\Bundle\AcmeBundle\Entity;

use Doctrine\ORM\EntityRepository;

class ArticleRepository extends EntityRepository
{
    public function getArticlesWithAuthors()
    {
        $qb = $this->createQueryBuilder('article');

        $query = $qb
            ->select('article, author')
            ->innerJoin('article.author', 'author')
            ->orderBy('a.id', 'DESC')
        ;

        return $query->getQuery()->getResult();
    }
}

然后就可以调用方法了:

$articles = $em->getRepository('MyBundle:Article')->getArticlesWithAuthors();

Doctrine 会在同一个查询中加载与文章关联的作者。

【讨论】:

  • "要知道你必须显示什么值,Symfony 应该遍历循环以猜测你需要什么值,在获取数据之前需要做很多工作。" - 从技术上讲,它无法进行查询,直到它同时获得控制器和视图所需的数据并基于两者进行查询而不是进行 2 个查询。
  • @GeorgeIrimiciuc 是的,你是对的,Doctrine 应该可以遍历循环并找到需要的值。无论如何,如果您查看 Profiler,您将看到查询是在 Controller 中执行的。我认为 Symfony 决定在渲染 Twig 模板之前缓存 Doctrine 结果。
  • 我想知道为什么。以损失的表现进行交易必须是一个重要的理由。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多