Php 在内部连接中启动太多查询

Php 在内部连接中启动太多查询,php,mysql,symfony,doctrine,Php,Mysql,Symfony,Doctrine,有了这段代码,条令启动的查询就和我在表2中的行一样多 $qb = $this->getModelManager()->createQuery($er->getClassName(), 't1')->getQueryBuilder(); $qb->select('t1, t2, t3') ->innerJoin('table1.table2', 't2'); ->innerJoin('table2.table3', 't3') ->

有了这段代码,条令启动的查询就和我在表2中的行一样多

$qb = $this->getModelManager()->createQuery($er->getClassName(), 't1')->getQueryBuilder();

$qb->select('t1, t2, t3')
   ->innerJoin('table1.table2', 't2');
   ->innerJoin('table2.table3', 't3')
   ->where('t3.id = :foo')
   ->setParameter('foo', $foo);
每个查询都类似于以下查询:

SELECT t0.id AS id_1,
       t0.name AS name_2, 
       t0.slug AS slug_3,
       t0.description AS description_4, 
       t0.visible AS visible_5 
FROM table2 t0 
WHERE t0.id = ?
这些实体是:

表1:如果我使表2的innerJoin按预期运行(1个查询),则主实体(它与表2通过manytone关联)

表2分别与表1和表3相关

/**
 * @ORM\Entity(repositoryClass="table2Repository")
 * @ORM\Table(name="table2")
 */
class table2 extends Basetable2
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="table3", inversedBy="table2s")
     * @ORM\JoinTable(name="table3_table2")
     */
    protected $table3;

    /**
     * @ORM\OneToMany(targetEntity="table1", mappedBy="table2")
     * @Accessor(getter="getTables1")
     */
    protected $tables1;
}
表3:oly通过多个关系与表2相关。当我使用表2进行innerJoin时,Doctrine仍按预期操作,只进行一次查询

/**
 * @ORM\Entity(repositoryClass = "table3Repo")
 * @ORM\Table(name="table3")
 * @Gedmo\Loggable
 */
class table3 extends Basetable3
{
    /**
     * @ORM\Id 
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="table2", mappedBy="tables3")
     * @ORM\JoinTable(name="table3_table2")
     */
    protected $tables2;
}
因此,当我将两个内部连接添加到查询生成器时,条令只进行一个查询,但当我添加WHERE子句时,条令进行279个查询,表2中每行一个查询,其中一个查询与表1相关,多个查询与表3相关

另一个相关点是querybuilder是在SonataAdmin查询构建器fiel选项下执行的


我找不到为什么我会有这种行为,有什么线索吗?

当你运行一个查询时,你总是需要一个根实体来连接其他实体。在您的情况下,这就是
表1
。获取后,基于查询和实体元数据,
doctor
将尝试为root的每个实例创建一个对象,但除非另有说明,否则它将停止。事实上,对于每个子对象(例如,
表2
),它将创建虚拟“代理”对象,这些对象仅仅是浅层表示,只要尝试取消引用它们,就会从DB解析。将DB结果转换为对象的过程称为对象水合

为了执行子对象的水合作用,还需要“选择”子实体:

$qb->select('t1', 't2', 't3')
    ->innerJoin('t1.table2', 't2');
    ->innerJoin('t2.table3', 't3')
    ->where('t3.id = :foo')
    ->setParameter('foo', $foo);
注意不要抓取所有东西而发疯,因为它需要更长的时间,并且消耗更多的内存。微调您的查询,直到达到您想要的(逻辑和性能方面)


希望这对您有所帮助。

当您运行查询时,您总是需要有一个与其他实体连接的根实体。在您的情况下,这就是
表1
。获取后,基于查询和实体元数据,
doctor
将尝试为root的每个实例创建一个对象,但除非另有说明,否则它将停止。事实上,对于每个子对象(例如,
表2
),它将创建虚拟“代理”对象,这些对象仅仅是浅层表示,只要尝试取消引用它们,就会从DB解析。将DB结果转换为对象的过程称为对象水合

为了执行子对象的水合作用,还需要“选择”子实体:

$qb->select('t1', 't2', 't3')
    ->innerJoin('t1.table2', 't2');
    ->innerJoin('t2.table3', 't3')
    ->where('t3.id = :foo')
    ->setParameter('foo', $foo);
注意不要抓取所有东西而发疯,因为它需要更长的时间,并且消耗更多的内存。微调您的查询,直到达到您想要的(逻辑和性能方面)


希望这有帮助…

已经尝试过了,但是仍然会对查询发疯,谢谢。嗯,如果我没有弄错的话,您不能通过“table1.id”加入,因为这是非关系属性。我已经调整了答案以反映实体结构。。。你能试试吗?做了,什么都没有,我更新了问题。再次感谢。这似乎很奇怪。不管怎么说,这应该是可行的。关于这个问题,你还有什么可以分享的信息吗?已经尝试过了,但是仍然会被查询搞疯,谢谢。嗯,如果我没有弄错的话,你不能通过“table1.id”加入,因为这是非关系属性。我已经调整了答案以反映实体结构。。。你能试试吗?做了,什么都没有,我更新了问题。再次感谢。这似乎很奇怪。不管怎么说,这应该是可行的。关于这个问题你还有什么可以分享的信息吗?这是任何ORM的标准行为。阅读如何使用。嗯,我知道很多方法都涉及查询两个实体之间的中间表,但ORM并不是这样做的,它获取其中一个表中的所有数据,并检索表中所有行的对象,这是我不理解的。事实上,查询是在我对已通过内部联接获取的数据进行where时完成的。这些查询不是查询本身的结果,而是视图中对象图遍历的结果。这是任何ORM的一个相当标准的行为。阅读如何使用。嗯,我知道很多方法都涉及查询两个实体之间的中间表,但ORM并不是这样做的,它获取其中一个表中的所有数据,并检索表中所有行的对象,这是我不理解的。事实上,查询是在我对已通过内部联接获取的数据进行where时完成的。查询不是查询本身的结果,而是视图中对象图遍历的结果。