【问题标题】:Force Doctrine to Load Associated Entities in JOIN强制 Doctrine 在 JOIN 中加载关联实体
【发布时间】:2014-11-21 23:32:38
【问题描述】:

问题

强制原则从查询 JOIN 加载嵌套关联实体的最佳方法是什么?

详情

我有多个实体(viewcontentTypeversionsettings),具有三个级别的关联:

view               (primary entity)
    contentType    (ManyToOne joined on view.contentTypeId = contentType.id)
    version        (OneToMany joined on version.viewId = view.id)
        settings   (OneToOne joined on settings.versionId = version.id)

我有一个查询所有版本(不是视图)的列表,以获取最近修改的版本。但我从viewcontentTypesettings 访问属性。我通过view 访问contentType(所以它有两层深)。当我在循环中引用这些属性时,我不希望 Doctrine Lazy Loading 每个值,每个循环都有 N 个查询。

所以我在查询中加入实体,并选择所有字段。

$versionRepo = $em->getRepository('GutensiteCmsBundle:View\ViewVersion');
$queryBuilder = $versionRepo->createQueryBuilder('e')
    ->join('e.view', 'view')
    ->addSelect('view')
    ->join('view.contentType', 'contentType')
    ->addSelect('contentType')
    ->join('e.settings', 'settings')
    ->where('e.siteId = :siteid')->setParameter('siteId', 1)
    ->setMaxLimit(25);

第一级链接被正确获取,例如version.view。但是,学说处理 version.settings 就像延迟加载一样,我将有 25 个额外的查询来加载每个单独的值。

所以即使我加入了settings,它仍然是延迟加载。

【问题讨论】:

    标签: symfony doctrine-orm doctrine


    【解决方案1】:

    如果您想避免延迟加载(推荐用于循环),Doctrine 建议您在查询时加入实体。但是您还必须将实体添加到 SELECT 语句中,例如

    ->join('e.settings', 'settings')
    ->addSelect('settings')
    

    From the Doctrine Docs on Join

    SELECT 查询可以包含连接。 JOIN 有 2 种类型: “常规”连接和“获取”连接。

    Regular Joins:用于限制结果和/或计算聚合 价值观。

    Fetch Joins:除了常规join的用途外:用于获取 相关实体并将它们包含在查询的水合结果中。

    没有特殊的 DQL 关键字可以区分常规连接和 获取连接。一个连接(无论是内连接还是外连接)变成了“获取 加入”,只要加入实体的字段出现在 SELECT 部分 聚合函数之外的 DQL 查询。否则它是一个 “常规加入”。

    Doctrine 还建议您可以使用 Query Hints 来“水合对象,尽管并非所有列都已获取。”

    $query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
    

    如果您不想加入,可以考虑一下。

    【讨论】:

      猜你喜欢
      • 2014-09-30
      • 1970-01-01
      • 2018-04-09
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多