使用Symfony 3.2和Doctrine 2.5,我很难理解"渴望"如何在多对多和多一的关系中起作用。
可以说,我们有两个实体,用户和网站,以及一个多对多的关联:
class User
{
/**
* @ORMManyToMany(targetEntity="Site", inversedBy="users", fetch="EAGER")
* @ORMJoinTable(name="user_site")
*/
private $sites;
}
class Site
{
/**
* @ORMManyToMany(targetEntity="User", mappedBy="sites")
*/
private $users;
}
在我的控制器中,我只需致电
$users = $this->getDoctrine()->getRepository('CoreBundle:User')->findAll();
我只想在用户表上看到1个查询,并在网站表上加入一个查询,但是我得到了n 1个查询。我还进行了一些与一对一关联的测试,并获得了相同的结果。
我知道我可以使用DQL自己进行加入,但我想了解"渴望"的工作方式。
在多对多和一对一的关联上以"急切"的"渴望"的预期行为是什么?
多到马尼
many-to-many
关联上提取eager
的预期行为正是您所描述的。
如果我们在代码中访问3个Post
对象,这些对象与Tags
有一个many-to-many
关联,则发生4个查询,无论我们使用fetch="EAGER"
还是fetch="LAZY"
:
SELECT t0.id AS id_1, t0.title AS title_2 FROM post t0
SELECT t0.id AS id_1, t0.title AS title_2 FROM tag t0 INNER JOIN post_tag ON t0.id = post_tag.tag_id WHERE post_tag.post_id = 1
SELECT t0.id AS id_1, t0.title AS title_2 FROM tag t0 INNER JOIN post_tag ON t0.id = post_tag.tag_id WHERE post_tag.post_id = 2
SELECT t0.id AS id_1, t0.title AS title_2 FROM tag t0 INNER JOIN post_tag ON t0.id = post_tag.tag_id WHERE post_tag.post_id = 3
一到一对
one-to-many
关联上使用eager
的预期行为不同。通过使用fetch="EAGER"
,我们可以减少查询数量。
如果我们在代码中访问3个Post
对象,该对象与Comments
具有one-to-many
关联时,使用fetch="EAGER"
时会发生1个查询:
SELECT
t0.id AS id_1,
t0.title AS title_2,
t3.id AS id_4,
t3.title AS title_5,
t3.post_id AS post_id_6
FROM post t0
LEFT JOIN comment t3 ON t3.post_id = t0.id
但是,如果我们使用 fetch="LAZY"
:
SELECT t0.id AS id_1, t0.title AS title_2 FROM post t0
SELECT t0.id AS id_1, t0.title AS title_2, t0.post_id AS post_id_3 FROM comment t0 WHERE t0.post_id = 1
SELECT t0.id AS id_1, t0.title AS title_2, t0.post_id AS post_id_3 FROM comment t0 WHERE t0.post_id = 2
SELECT t0.id AS id_1, t0.title AS title_2, t0.post_id AS post_id_3 FROM comment t0 WHERE t0.post_id = 3
我的结论
永远不要在many-to-many
关联上使用fetch="EAGER"
,因为它只能通过从DB中加载更多的数据来减慢您的性能(但永远无法改进(。如果可以改善您的性能,请选择使用one-to-many
上的fetch="EAGER"
。
如果我们需要减少many-to-many
关联的查询,我们必须编写自定义DQL查询。