强制学说从查询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)
我有一个列表,查询所有版本(不是视图)以获取最近修改的版本。但我从view
和contentType
以及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
,它仍然是延迟加载。
答案 0 :(得分:11)
如果你想避免延迟加载(推荐用于循环),Doctrine建议你在查询时加入一个实体。但是你还必须将实体添加到SELECT语句中,例如
->join('e.settings', 'settings')
->addSelect('settings')
SELECT查询可以包含联接。有两种类型的JOIN: “常规”加入和“获取”联接。
常规联接:用于限制结果和/或计算聚合 值。
获取联接:除了使用常规联接之外:用于获取 相关实体,并将它们包含在查询的水合结果中。
没有特殊的DQL关键字可以区分常规连接 获取连接。连接(无论是内部连接还是外部连接)成为“获取” 加入“只要连接实体的字段出现在SELECT部分中 在聚合函数之外的DQL查询。否则它的a “定期加入”。
Doctrine还建议您可以使用Query Hints“水合对象,尽管并非所有列都被提取。”
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
如果您不想加入,可以查看此内容。