2016-01-23 67 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