Doctrine orm 原则2:查询多对多关联的有效方法

Doctrine orm 原则2:查询多对多关联的有效方法,doctrine-orm,dql,Doctrine Orm,Dql,我在两个表(特许经营和玩家)之间有一个多对多的关联,它是用一个额外的表(特许经营和玩家)构建的。 我创建了三个实体: class Franchise { ... /** * * @var ArrayCollection * * @ORM\OneToMany(targetEntity="NBA\Entity\FranchisePlayer", mappedBy="franchise") */ private $fran

我在两个表(特许经营和玩家)之间有一个多对多的关联,它是用一个额外的表(特许经营和玩家)构建的。 我创建了三个实体:

class Franchise 
{
    ...
    /**
     * 
     * @var ArrayCollection
     * 
     * @ORM\OneToMany(targetEntity="NBA\Entity\FranchisePlayer", mappedBy="franchise")
     */
    private $franchiseplayers;
    ...
}

class Player
{
    /* some fields */
}

class FranchisePlayers 
{
    ...
    /**
     * @var \NBA\Entity\Player
     *
     * @ORM\ManyToOne(targetEntity="NBA\Entity\Player")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="playerId", referencedColumnName="id")
     * })
     */
     private $player;

     /**
      * @var \NBA\Entity\Franchise
      *
      * @ORM\ManyToOne(targetEntity="NBA\Entity\Franchise")
      * @ORM\JoinColumns({
      *   @ORM\JoinColumn(name="franchiseId", referencedColumnName="id")
      * })
      */
      private $franchise;
}
我的目标是获得所有与他们相关的球员的特许经营权

显而易见的解决方案很简单,但效率不高:

Get all franchises
foreach $franchise
    $franchise->getFranchisePlayers()
    foreach $franquisePlayer
        $franquisePlayer->getPlayer()->getFullName();
另一种解决方案是获得所有特许经营权,然后执行左联合,以获得每个特许经营权的相关玩家:

Get all franchises
foreach $franchise
    public function getCurrentPlayers(Franchise $franchise) {   

    $qb = $this->entityManager->createQueryBuilder();
    $qb->select(array('p'))
       ->from('NBA\Entity\Player', 'p')
       ->leftjoin('NBA\Entity\FranchisePlayer','f','WITH','f.player=p')
       ->where('f.franchise = ?1')
       ->orderBy('p.surname','ASC')
       ->setParameter(1,$franchise);

    $query = $qb->getQuery();
    return $query->getResult();
}
通过这种方式,我们减少了查询的数量

我的问题是,我是否可以通过这样一个查询来实现我的目标:

public function getFranchisesWithPlayers() {
    $qb = $this->entityManager->createQueryBuilder();
    $qb->select(array('f'))
        ->from('NBA\Entity\Franchise', 'f')
        ->leftJoin('NBA\Entity\FranchisePlayer','fp','WITH','fp.franchise=f')
        ->leftJoin('NBA\Entity\Player','p','WITH','fp.player=p')
        ->orderBy('f.name')
        ->addOrderBy('p.surname');

    $query = $qb->getQuery();
    return $query->getResult();     
}
我认为特许经营实体的特许经营玩家字段(以及每个特许经营玩家的de-Player实体)将自动加载,但这似乎不是真的

有可能吗?也许我在实体的映射中做错了什么

谢谢大家!


编辑:昨天我确信少查询的查询效率最高,但现在我怀疑。可能这个复杂查询结果的水合成本大于选项2查询结果的水合成本(针对不同查询中每个特许权的玩家的查询)。您觉得怎么样?

文档展示了如何创建查询。也许值得一看。比如:

$qb->select('franchise,franchisePlayer,player')
    ->from('NBA\Entity\Franchise', 'franchise')
    ->leftJoin('franchise.franchisePlayers','franchisePlayer')
    ->leftJoin('franchisePlayer.player','player')
    ->orderBy('franchise.name')
    ->addOrderBy('player.surname');

我已经检查了你的建议,但是这个查询返回一个不同对象的数组。第一个要素是特许经营,但第二个要素是特许经营球员,第三个要素是球员,第四个要素也是特许经营球员。也就是说,我在一个查询中就得到了我想要的所有对象(太棒了!),但混合在同一个数组中。只是为了集中问题:我想获得一个特许权数组,其中特许权玩家字段已经加载(为了避免额外的查询)。这些玩家对象也应该加载玩家字段。再次检查。如图所示的查询将返回特许经营对象列表。谢谢,你完全正确。我没有正确构建查询。您认为只执行一个查询更有效,还是对每个特许经营权执行一个查询更好,以便获得相关玩家?对于这些类型的查询,当您知道需要所有附加信息时,单个查询通常是最好的。当你有很多很多关系的时候,事情可能会开始变慢。但每个案例都会有所不同。