学说2:查询多对多关联的有效方法

时间:2016-01-23 15:10:08

标签: doctrine-orm dql

我在两个表(特许经营和玩家)之间建立了多对多关联,并使用附加表(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();     
}

我认为特许经营实体的franchisePlayers字段(以及每个FranchisePlayer的de Player实体)将自动加载,但似乎这不是真的。

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

谢谢!

编辑:昨天我确信查询效率最低,但现在我很怀疑。也许将这个复杂查询的结果加水化的成本大于水合选项2的查询的每个结果(在不同查询中查询每个特许经营者的玩家)的成本。你觉得怎么样?

1 个答案:

答案 0 :(得分: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');