gpt4 book ai didi

symfony - Doctrine2一对多获取= EAGER如何工作?

转载 作者:行者123 更新时间:2023-12-04 15:09:32 24 4
gpt4 key购买 nike

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

我有2个实体,Gallery OneToMany File

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

我在文档中看到两件事。

首先,现在OneToMany关系确实具有 fetch=EAGER选项( specified here)。在以前的版本中不存在。

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

Changing the fetch mode during a query is only possible for one-to-one and many-to-one relations.



无论如何我都尝试过这两个,这是我的查询:
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)
我错过了什么?这种行为是在学说中实现的吗?

latest doctrine changelog指出:

When marking a one-to-many association with fetch="EAGER" it will now execute one query less than before and work correctly in combination with indexBy.



根本不清楚预期的行为是什么。

欢迎任何有识之士,谢谢!

最佳答案

经过大量搜索和测试(在Doctrine ORM 2.5.6上使用PHP 5.6),我得到了一些结果。

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

你有两个选择

使用Left Join在一个查询中获取库和文件实体。

  • 当您在注释上设置->find*时,这就是fetch="EAGER"方法的作用。
  • 您可以使用DQL手动执行此操作:SELECT g, f FROM Gallery g LEFT JOIN g.files f

  • 作为 noted in the docs,您不能在DQL查询上调用 ->setFetchMode('Gallery', 'files', ClassMetadata::FETCH_EAGER)来获得相同的结果

    ... For one-to-many relations, changing the fetch mode to eager will cause to execute one query for every root entity loaded. This gives no improvement over the lazy fetch mode which will also initialize the associations on a one-by-one basis once they are accessed.



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

    通过一个查询获取Gallery实体并延迟加载File实体。
  • 这是Doctrine的默认行为(fetch="LAZY"),将导致1个查询,以及对您访问的每组Gallery#$files的附加查询(如果全部访问,则为1 + n个查询)。

  • future 可能的选择

    有一个 PR to add an EAGER_BATCHED fetch option可以完全满足您的要求(通过一个查询获取 Gallery实体,然后通过第二个查询获取所有 File实体),但是不幸的是,它并没有发生太多事情。

    结论

    如果您使用的是 ->find*方法,则将遵守 fetch="EAGER"批注。教义将通过“左联接”来做到这一点。根据您的数据集,这可能还可以,也可能非常昂贵。

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

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

    关于symfony - Doctrine2一对多获取= EAGER如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34216199/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com