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

Cha*_*yer 4 doctrine symfony doctrine-orm

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

细节

我有多个实体(view,contentType,version,settings),有三个关联级别:

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)
Run Code Online (Sandbox Code Playgroud)

我有一个列表查询所有版本(不是视图)以获取最近修改的版本.但我从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);
Run Code Online (Sandbox Code Playgroud)

第一级链接ARE正确获取,例如version.view.但是,doctrine处理version.settings类似于延迟的负载,并且我将有25个额外的查询来加载每个单独的值.

所以即使我加入settings它仍然是懒惰加载.

Cha*_*yer 11

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

->join('e.settings', 'settings')
->addSelect('settings')
Run Code Online (Sandbox Code Playgroud)

来自Doctrine Docs on Join

SELECT查询可以包含联接.有两种类型的JOIN:"常规"连接和"获取"连接.

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

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

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

Doctrine还建议您可以使用查询提示 "水合对象,尽管并非所有列都被提取".

$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
Run Code Online (Sandbox Code Playgroud)

如果您不想加入,可以查看这些内容.