Symfony2 中的 Doctrine2 (Doctrine 2.1) 急切加载
假设我的 Symfony2 项目中有两个实体:Category
和 Article
(一个包含许多文章的类别)。
在我的CategoryRepository
中,我有这个方法:
findAllDummy(){
return $this->createQueryBuilder('c')
->leftJoin('c.Articles a')
->getQuery()->getResult();
}
如果我没记错的话,在Symfony1.4(以及相应版本的Doctrine)中,返回的对象的'articles'属性将由相应的填充>Article
对象。 现在,在 Symfony2 中,返回 Proxy 对象。
因此,如果我循环浏览特定类别的文章,将执行与迭代一样多的查询。
foreach($category->getArticles() as $article){
echo $article->getDoctrine()
->getRepository('')getTitle();
}
我知道这是 Doctrine2.1 的默认延迟加载行为。
问题 1:这是一个更好的解决方案吗? N 个查询而不是 1 个。
我尝试通过执行以下操作强制预先加载:
findAllDummy(){
return $this->createQueryBuilder('c')
->leftJoin('c.articles a')
->getQuery()
->setFetchMode('Category', 'articles', 'EAGER')
->getResult();
}
但结果保持不变。
问题2:如何在Doctrine2中强制预先加载?
Let's say I have two entities in my Symfony2 project : Category
and Article
(a category having many articles).
In my CategoryRepository
, I have this method:
findAllDummy(){
return $this->createQueryBuilder('c')
->leftJoin('c.Articles a')
->getQuery()->getResult();
}
If I remember well, in Symfony1.4 (and the corresponding version of Doctrine), the returned objects would have their 'articles' attribute filled by the corresponding Article
objects.
Now, in Symfony2, Proxy objects are returned.
So if I loop through a specific category's articles, As many queries as iterations will be executed.
foreach($category->getArticles() as $article){
echo $article->getDoctrine()
->getRepository('')getTitle();
}
I understand this is Doctrine2.1's default lazy loading behavior.
Question 1: how is this a better solution?
N queries instead of 1.
I tried to force eager loading by doing the following:
findAllDummy(){
return $this->createQueryBuilder('c')
->leftJoin('c.articles a')
->getQuery()
->setFetchMode('Category', 'articles', 'EAGER')
->getResult();
}
But the result remains the same.
Question 2: how to force eager loading in Doctrine2?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您正在加入一个表,但没有从中选择任何内容。将
->addSelect('a')
添加到您的查询生成器。考虑以下两个 SQL 查询以了解差异:急切/惰性连接与 DQL 查询无关。它定义了使用
$articleRepository->find(123)
时应加载的内容。You're joining a table but you're not selecting anything from it. Add
->addSelect('a')
to your query builder. Consider two following SQL queries to understand the difference:Eager/lazy joining has nothing to do with DQL queries. It defines what should be loaded when you use
$articleRepository->find(123)
.在您尝试“强制预先加载”的部分中,问题可能是您使用
fetchMode
方法以及$fetchMode
的变量类型错误代码> 参数。您传递了一个字符串'EAGER'
,但该方法不需要一个字符串,而是一个整数。该方法需要来自 ClassMetadata 类的常量:
在 Doctrine 文档章节 14.7.6.6 中。暂时更改 DQL 中的获取模式,您可以查看有关如何使用此模式的示例:
因此,传递对常量的引用或与您要使用的模式相对应的整数。
In the part where you try to "force eager loading" the problem might be that you use the
fetchMode
method with the wrong variable type for the$fetchMode
argument. You pass a string'EAGER'
but the method doesn't expect a string but an integer.The method expects constants from the
ClassMetadata
class:In the Doctrine documentation chapter 14.7.6.6. Temporarily change fetch mode in DQL you can see an example on how to use this:
So pass either a reference to the constant or an integer that corresponds to the mode you want to use.
正如doctrine docs,在这种情况下急切加载不会产生任何影响,因为类别和文章之间存在一对多关系。
因此,与 @Crozin 所说的相反,您仍然可以在 DQL 中进行预先加载。
如果您有一对一或多对一的关系,急切加载将解决进行额外查询的问题。但是,要解决这种情况下的问题,您应该使用
->addSelect('a')
正如 @Crozin 提到的。As it says in the doctrine docs, eager loading in this case won't make any difference because you have one-to-many relationship between Category and Article.
So contrary to what @Crozin has said, you can still do eager loading in DQL.
If you have a one-to-one or many-to-one relationship, eager loading will solve the problem of making extra queries. However to solve your problem in this case you should use
->addSelect('a')
as @Crozin mentioned.这是一个更好的解决方案,因为连接是一个比简单查询昂贵得多的过程。虽然它可能看起来效率低下,但它并没有太大的浪费,并且当您不加载每个相关对象的所有部分时,它很快就会变得更加高效。
It is a better solution because joins are a much more expensive process than a simple query. While it may seem inefficient, it isn't much of a waste, and quickly becomes more efficient when you aren't loading every bit of every related object.