【问题标题】:Doctrine partial queries return the complete objectDoctrine 部分查询返回完整对象
【发布时间】:2013-08-28 20:32:16
【问题描述】:

我正在尝试优化查询,因为我需要一个简单的列表作为隶属于多个实体的实体。 所以我创建了这个查询,你应该把 id 和 name 还给我:

public function findAllOrderByName() {
    $qb = $this->createQueryBuilder('a');
         $query = $qb->select(array('partial a.{id,name}'))
                 ->addOrderBy('a.name', 'ASC')
                 ->getQuery();

         return $query->getResult();
}

像这样在控制器中返回它:

public function getInstrumentsAction()
{
    $instruments = $this->getDoctrine()->getRepository('AcmeInstrumentBundle:Instrument')->findAllOrderByName();

    return array('instruments' => $instruments);
}

与其把两个阵营还给我,还给我完整的对象,从而包括其他相关实体的所有领域。

为什么它不起作用?

【问题讨论】:

    标签: symfony doctrine-orm symfony-2.3


    【解决方案1】:

    它实际上完全按照设计工作。您正在观察的是相关实体的延迟加载。

    从添加开始:

    echo $query->getSQL() . "\n";
    return $query->getResult();
    

    你会看到类似的东西:

    SELECT p0_.id AS id0, p0_.name AS name1 FROM instrument p0_ ORDER BY p0_.name ASC
    

    所以只有您要求的两个字段实际被查询。

    echo sprintf("Instrument %s %s %s\n",
         $instrument->getName(),$instrument->getSomeotherScalervalue());
    

    您会看到,虽然名称被回显,但其他一些值即使在仪器表中也没有。

    就关系而言,让我们假设工具与人具有 oneToMany 关系。

    $persons = $instrument->getPersons();
    

    您可能会认为 $persons 是一个空数组,但它实际上是一个相当聪明的 Doctrine\ORM\PersistentCollection。只要您尝试使用 $person 做任何其他事情(即使是像 count($persons) 这样简单的事情,就会触发另一个查询,并且所有链接的 person 对象都将被加载。

    这就是你所看到的。您实际上可以在您的日志/dev.log 中看到查询。只要您只是拉入仪器,那么只会生成一个查询。只要您尝试对关系执行某些操作,就会发出另一个查询。

    工作环境

    1. 不要尝试访问关系。

    2. 在访问关系之前,您可以执行 $persons->setInitialized(true);这将阻止加载。显然有点痛。

    3. 既然优化是您的目标,那么只需返回一个数组结果。根本没有物体。

    4. 您也可以继续并在查询中加入您的关系,但使用 partial 来输入相关实体的 id。您的查询会更难一些,但您不必担心会触发其他查询。

    如果有某种方法可以防止基于查询的延迟加载,那就太好了。但如果有的话,我一直没能找到。

    【讨论】:

    • 非常感谢您的解释!有一件事我不明白.. 在 dev.log 实际上我看到使用这个查询:SELECT i0_.id AS id0, i0_.name AS name1 FROM Instrument i0_ ORDER BY i0_.name ASC [] [] 但是当我传递对象时,我是关联实体的所有信息。不知何故会通过延迟加载来补充水分.. 然而,虽然我不确定,但在我看来,使用 getArrayResult() 执行速度更快,那么逻辑应该已经排除了我不需要的所有数据!
    • 并非如此。在大多数情况下,延迟加载是一件好事。我想你可能会争辩说使用部分应该禁用延迟加载,但它可能会变得复杂。您可以在教义留言板上展开讨论。
    • 感谢您的建议!
    猜你喜欢
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多