Php 在内部连接中启动太多查询
有了这段代码,条令启动的查询就和我在表2中的行一样多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') ->
$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时完成的。查询不是查询本身的结果,而是视图中对象图遍历的结果。