2016-01-23 52 views
1

我在两张表(特许经营和玩家)之间建立了一个多对多的关联,用另外一张表(franchise_players)构建。 我已创建了三个实体:学说2:查询多对多关联的有效方式

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

另一种解决方案是让所有的特许经营权,然后执行LEFT JOIN来获取每一个特许经营相关的球员:

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

我认为特许经营实体(每FranchisePlayer也去球员实体)的franchisePlayers领域将自动加载,但似乎这是不正确的。

是否可以做到这一点?也许我在我的实体的映射中做错了什么?

谢谢!

编辑:昨天我确信越少查询效率最高,但现在我怀疑。也许这种复杂查询的结果水成本大于选项2查询的每个结果的花费(在不同查询中查询每个特许经营者的球员)。你怎么看?

回答

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'); 
+0

我已经检查了您的建议,但此查询返回不同对象的数组。第一个元素是特许经营,但第二个元素是特许经营者,第三个是玩家,第四个是特许经营者。也就是说,我只用一个查询就能得到所需的所有对象(太棒了!),但它们混合在同一个数组中。 – TxusMa

+0

只是为了聚焦这个问题:我想要获得已经加载的franchisePlayers字段的一系列特许经营权(以避免额外的查询)。而且这些特许玩家对象应该也加载了玩家领域。 – TxusMa

+0

再次检查。所显示的查询将返回特许经营对象列表。 – Cerad