强制学说在JOIN中加载关联实体

时间:2014-11-21 23:32:38

标签: symfony doctrine-orm doctrine

问题

强制学说从查询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)

我有一个列表,查询所有版本(不是视图)以获取最近修改的版本。但我从viewcontentType以及settings访问了属性。我通过contentType访问view(所以它的深度是两级)。当我在循环中引用这些属性时,我不希望Doctrine Lazy为每个循环加载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。但是,doctrine处理version.settings就像延迟加载一样,我会在25个额外的查询中加载每个单独的值。

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

1 个答案:

答案 0 :(得分:11)

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

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

From the Doctrine Docs on Join

  

SELECT查询可以包含联接。有两种类型的JOIN:   “常规”加入和“获取”联接。

     

常规联接:用于限制结果和/或计算聚合   值。

     

获取联接:除了使用常规联接之外:用于获取   相关实体,并将它们包含在查询的水合结果中。

     

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

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

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

如果您不想加入,可以查看此内容。