Doctrine2(Doctrine 2.1)在Symfony2中急切加载

时间:2012-01-12 14:07:42

标签: symfony doctrine doctrine-orm lazy-loading

假设我的Symfony2项目中有两个实体:CategoryArticle(一个包含很多文章的类别)。

在我的CategoryRepository中,我有这个方法:

findAllDummy(){
  return $this->createQueryBuilder('c')
              ->leftJoin('c.Articles a')
              ->getQuery()->getResult();
}

如果我记得很清楚,在Symfony1.4(以及相应的Doctrine版本)中,返回的对象的“articles”属性将由相应的Article对象填充。 现在,在Symfony2中,返回代理对象。

因此,如果我遍历特定类别的文章,将执行与迭代一样多的查询。

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中强行加载?

4 个答案:

答案 0 :(得分:18)

你正在加入一张桌子,但你没有从中选择任何东西。将->addSelect('a')添加到查询构建器。考虑以下两个SQL查询来理解差异:

SELECT a.id, a.title
FROM article a 
JOIN category c ON a.category_id = c.id 
WHERE a.id = 123;

SELECT a.id, a.title, c.id, c.name 
FROM article a 
JOIN category c ON a.category_id = c.id 
WHERE a.id = 123;

渴望/懒惰加入与DQL查询无关。它定义了使用$articleRepository->find(123)时应该加载的内容。

答案 1 :(得分:2)

在您尝试“强制加载”的部分中,问题可能是您使用p+n方法使用错误的变量类型fetchMode参数。传递字符串$fetchMode但该方法不期望字符串而是整数。

该方法需要来自'EAGER'类的常量:

ClassMetadata

在Doctrine文档章节 14.7.6.6中。暂时更改DQL中的获取模式,您可以看到有关如何使用它的示例:

/**
 * Specifies that an association is to be fetched when it is first accessed.
 */
const FETCH_LAZY = 2;

/**
 * Specifies that an association is to be fetched when the owner of the
 * association is fetched.
 */
const FETCH_EAGER = 3;

因此传递对常量的引用或对应于您要使用的模式的整数。

答案 2 :(得分:0)

正如doctrine docs中所述,在这种情况下,急切加载不会有任何区别,因为你在类别和文章之间有一对多的关系。

  

对于一对多关系,将获取模式更改为eager将导致为每个加载的根实体执行一个查询。与惰性提取模式相比,这没有任何改进,一旦访问它们,它也将逐个初始化关联。

与@Crozin所说的相反,你仍然可以在DQL中进行急切加载。 如果您具有一对一或多对一关系,则急切加载将解决进行额外查询的问题。但是,要在这种情况下解决您的问题,您应该使用->addSelect('a')作为@Crozin提及。

答案 3 :(得分:-2)

这是一个更好的解决方案,因为连接是一个比简单查询更昂贵的过程。虽然它看起来效率低下,但它并不是很浪费,当你没有加载每个相关对象的每一点时,它会很快变得更有效率。