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

Doctrine 2: Efficient way to query a many-to-many association

我在两个 table 之间建立了多对多关联(特许经营权和球员),建立了一个额外的 table (franchise_players)。 我已经创建了三个实体:

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();     
}

我认为 Franchise 实体的 franchisePlayers 字段(以及每个 FranchisePlayer 的 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');