当前位置:  开发笔记 > 编程语言 > 正文

Doctrine2 One-To-Many fetch = EAGER是如何工作的?

如何解决《Doctrine2One-To-Manyfetch=EAGER是如何工作的?》经验,为你挑选了1个好方法。

我正在使用Symfony 2.8/Doctrine ORM 2.5.2.

我有2个实体,GalleryOneToManyFile

class Gallery
{
    /**
     * @var File[]
     *
     * @ORM\OneToMany(targetEntity="File", mappedBy="gallery", fetch="EAGER")
     */
    private $files;
}

我在文档中看到了两件事.

首先,现在OneToMany关系确实有fetch=EAGER选项(在此处指定).它在以前的版本中不存在.

其次,对于OneToMany,每个查询的此获取方法的手动设置似乎不可用,但我不知道文档是否是最新的,因为它指出:

在查询期间更改提取模式只能用于一对一和多对一关系.

无论如何我都试过了,这是我的查询:

public function findWithEager()
{
    $qb = $this->createQueryBuilder('g');

    $query = $qb->getQuery();
    $query->setFetchMode("CommonBundle\\Entity\\Gallery", "files", ClassMetadata::FETCH_EAGER);

    return $query->getResult();
}

但当我这样做时:

foreach ($galleryRepository->findWithEager() as $gallery) {
    foreach ($gallery->getFiles() as $file) {
        $file->getId();
    }
}

然后我得到1 + n个查询.第一个是SELECT * FROM Gallery以下n个SELECT * FROM File WHERE id = :galleryId

我希望Doctrine做1 + 1个查询,第二个是查询 SELECT * FROM File WHERE id IN (:galleryListIds)

我错过了什么?这种行为是否在Doctrine中实现?

在最新的学说的changelog状态:

当使用fetch ="EAGER"标记一对多关联时,它现在将执行少于之前的一个查询,并与indexBy结合使用.

目前尚不清楚预期的行为是什么.

欢迎任何见解,谢谢!



1> jxmallett..:

一番搜索和一些测试后(使用Doctrine ORM 2.5.6PHP 5.6)我有一些成果。

目前,无法Gallery通过一个查询获取您的实体,File而通过第二个查询获取所有相关实体。

你有两个选择

使用在一查询中获取Gallery和File实体Left Join

这是->find*设置fetch="EAGER"注释时方法的作用。

您可以使用DQL手动执行此操作: SELECT g, f FROM Gallery g LEFT JOIN g.files f

如文档中所述,您不能调用->setFetchMode('Gallery', 'files', ClassMetadata::FETCH_EAGER)DQL查询来获得相同的结果

...对于一对多关系,将获取模式更改为渴望将导致对每个加载的根实体执行一个查询。这没有对惰性获取模式进行任何改进,后者会在访问关联后以一对一的方式初始化关联。

这将导致在您执行第一个查询以获取Gallery实体后立即运行n个其他查询。

通过一个查询获取Gallery实体,然后延迟加载File实体。

这是Doctrine的默认行为(fetch="LAZY"),将对每个Gallery#$files访问集产生1个查询和一个附加查询(如果全部访问,则为1 + n个查询)。

未来可能的选择

有一个PR添加了一个EAGER_BATCHEDfetch选项,它可以完全满足您的要求(Gallery通过一个查询获取实体,然后File通过第二个查询获取所有实体),但是不幸的是,发生的事情并不多。

结论

如果您使用的是->find*方法,fetch="EAGER"则将遵守注释。学说将通过左联接来实现。根据您的数据集,这可能还可以,也可能非常昂贵。

如果您是手动编写DQL或使用查询生成器,则必须LEFT JOIN一对多关系,并记住将要提取的所有实体添加到select子句中。

我的首选是在您希望热切地获取一对多关系时编写DQL,因为它可以使您的意图明确。

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有