- Published on
doctrine教程7---EXTRA_LAZY 关系
- Authors
-
-
- Name
- langziyang
-
接下来我们删除findAllOrdered中添加的addSelect和leftJoin,让代码依然产生N+1问题
主页这里我们并不需要每一个分类下FortuneCookie的所有数据,实际上只需要一个COUNT,所以相像一下我们把所有FortuneCookie数据都取出来仅仅 只是为了数一下有多少个,这并不是一个好的方法。
如果你也遇到这种情况,其实只需要在OneToMany里添加一个参数fetch: 'EXTRA_LAZY'
#[ORM\OneToMany(mappedBy: 'category', targetEntity: FortuneCookie::class,fetch: 'EXTRA_LAZY')]
private Collection $fortuneCookies;
但其实现在查询还是会为N+1,只不过除了主查询,其它的都变成了SELECT COUNT(*) FROM fortune_cookie t0 WHERE t0.category_id = ?
当你有 fetch: 'EXTRA_LAZY' 并且你只是计算一个集合关系时,Doctrine 足够聪明,可以只选择 COUNT 而不是查询所有数据。如果我们要循环这个集合并开始打印 FortuneCookie 数据,那么它仍然会对数据进行完整查询。但如果我们需要的只是对它们进行计数,那么 fetch: 'EXTRA_LAZY' 是一个很好的解决方案
分类展示页面自定义查询
接下来我们进入某一个分类,调试工具会检测出有两个查询,一个是查询Category,另一个是查询该分类下所有fortune cookies让我们发挥我们的 JOIN 技能,将其简化为一个查询
修改一下控制器里的代码并在存储库添加findWithFortunesJoin方法
public function showCategory(int $id, CategoryRepository $categoryRepo): Response
{
$category = $categoryRepo->findWithFortunesJoin($id);
if (!$category) {
throw $this->createNotFoundException('Category not found!');
}
return $this->render('fortune/showCategory.html.twig', [
'category' => $category
]);
}
我们可以看到现在只有一次查询了,虽然没有必要过度优化,但如果遇到 N+1 问题,可以通过 JOIN到相关表并选择其数据来解决它。
好的,到目前为止,Doctrine 已经返回了 Category 对象的集合或单个 Category 对象。这很酷,但是如果我们只需要一些数据而不是整个对象,比如几列、 COUNT 或 SUM 呢?接下来让我们深入探讨一下。