Doctrine 对一对多关系进行了许多查询

Posted

技术标签:

【中文标题】Doctrine 对一对多关系进行了许多查询【英文标题】:Doctrine makes many queries for one-to-many relationship 【发布时间】:2015-11-05 21:33:01 【问题描述】:

我有一个使用 Doctrine 作为 ORM 的 Symfony2 应用程序。在我的应用程序中,我有两个具有一对多关系的实体。一个实体是User,多个实体是Item。他们的关系配置如下:

用户:

oneToMany:
            items:
                targetEntity: App\Bundle\ItemBundle\Entity\Item
                fetch: EAGER
                mappedBy: user

项目:

manyToOne:
        user:
            targetEntity: App\Bundle\UserBundle\Entity\User
            fetch: EAGER
            inversedBy: items
            joinColumn:
                name: user_id
                referencedColumnName: id

问题是当我试图获取Users 和他们的Items 的列表时,Doctrine 会为每个用户创建单独的查询来获取它的项目。

查询本身非常简单:

    $entities = $em->getRepository('AppUserBundle:User')->findBy([], [], 30);

是否可以使用 Doctrine 在一个查询中自动获取用户的所有相关项目?

我正在使用带有版本的 SF 2.7.6 和学说库:

doctrine/annotations                 v1.2.7  Docblock Annotations Parser
doctrine/cache                       v1.5.1  Caching library offering an ob...
doctrine/collections                 v1.3.0  Collections Abstraction library
doctrine/common                      v2.5.1  Common Library for Doctrine pr...
doctrine/dbal                        v2.5.2  Database Abstraction Layer
doctrine/doctrine-bundle             1.6.0   Symfony DoctrineBundle
doctrine/doctrine-cache-bundle       1.2.1   Symfony Bundle for Doctrine Cache
doctrine/doctrine-migrations-bundle  1.1.1   Symfony DoctrineMigrationsBundle
doctrine/inflector                   v1.0.1  Common String Manipulations wi...
doctrine/instantiator                1.0.5   A small, lightweight utility t...
doctrine/lexer                       v1.0.1  Base library for a lexer that ...
doctrine/migrations                  v1.1.0  Database Schema migrations usi...
doctrine/orm                         v2.5.1  Object-Relational-Mapper for php

【问题讨论】:

确保您已清除缓存并且您显示的映射文件是实际使用的文件。让您不混合 yaml 和注释。您发布的内容应该有效。 我刚刚检查了所有这些,但仍然没有运气。 只是为了笑,尝试从您的查询中删除 30。涉及连接时,限制和偏移总是有点挑战。 【参考方案1】:

无论如何,我认为设置 Eager fetch 并不是一个好主意。

这样的东西应该可以正常工作:

$users = $this->getEntityManager()
    ->createQueryBuilder()->select('u, i') // key is to select both entities  
    ->from('YourBundle:User', 'u')
    ->join('u.item', 'i')
    ->getQuery()->getResult();

【讨论】:

我已经设法使用您的答案获取相关记录。从技术上讲,它可以工作,但会在数据上产生很大的开销。假设我与用户实体有多个一对多关系,并且想要一次返回 10000 条记录,并且每个用户都有 10 个项目和 10 个帐户。如果我为此使用 JOIN 方法,它将返回 10000 * 10 * 10 条记录。如果 Doctrine 可以进行 3 个单独的查询来获取这些数据,我会更喜欢。【参考方案2】:

您可以创建一个method in the repository 来执行连接以避免额外的查询。可以用您自己的实现替换 findBy 方法,但我更喜欢创建更具描述性的方法。

虽然 Symfony 文档中的示例使用 DQL,但如果您愿意,也可以使用 QueryBuilder

【讨论】:

我使用的是查询生成器,本题中的查询仅用于简化,结果是一样的。 如果您使用的是查询生成器,请发布查询。您将需要同时选择用户和项目。有很大的不同。

以上是关于Doctrine 对一对多关系进行了许多查询的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Doctrine 2 中正确添加一对多关系?

Symfony2 和 Doctrine:一对多关系

一对多还是多对多?

Django 无法确定使用一对一关系链接一对多的查询集

关于与查询构建器的“一对多”关系的教义内连接

Doctrine - 从反面查询一对多、单向的连接表关联