2016-01-11 36 views
1

我有大約60個實體,全部引用(manyToOne或oneToOne)到稱爲「項目」的「超級實體」。關於不相關實體的原則單一查詢(用於儀表板)

我正在開發一個儀表板,所以一旦選擇了項目,我必須得到所有引用該項目的「子」實體。

所以我必須:

class Entity1{ 
... 
/** 
* @ORM\OneToOne(targetEntity="Project") 
*/ 
protected $project; 
... 
} 

class Entity2{ 
... 

/** 
* @ORM\ManyToOne(targetEntity="Project") 
*/ 
protected $project; 
... 
} 

我當然可以這樣做:

$entitiesToCheckStatusFor = ['Entity1', 'Entity2', ..., 'Entity60', ]; 
    $entitiesStatus = []; 
    foreach ($entitiesToCheckStatusFor as $entityToCheckStatusFor){ 
     $entitiesStatus[$entityToCheckStatusFor] = $em->getRepository('AppBundle:'.$entityToCheckStatusFor)->findByProject($project); 
    } 

但這也意味着60個查詢。它遠非優雅。

我基本上需要一個JOIN在不相關的實體之間,這樣我可以做一個單一的查詢。

我想是這樣的:

$query = $em->createQuery('SELECT ai, pn, pb, pd p FROM AppBundle:Project p ' 
     . 'LEFT OUTER JOIN AppBundle:ProjectNotification pn WITH p.id = pn.project ' 
     . 'LEFT OUTER JOIN AppBundle:ProjectDetail pd WITH p.id = pd.project ' 
     . 'LEFT OUTER JOIN AppBundle:ProjectBenefit pb WITH p.id = pb.project ' 
     . 'LEFT OUTER JOIN AppBundle:ActionItem ai WITH p.id = ai.project ' 
     . 'WHERE p.id = :projectid' 
    )->setParameter('projectid', $project->getId()); 
    $mixedStuff = $query->getResult(); 

,但在沒有實體返回很多空的:

array:20 [▼ 
    0 => Project {#8285 ▶} 
    1 => null 
    2 => ProjectDetail {#3028 ▶} 
    3 => null 
    4 => ActionItem {#2978 ▶} 
    5 => null 
    6 => null 
    7 => ActionItem {#3191 ▶} 
    8 => null 
    9 => null 
    10 => ActionItem {#3200 ▶} 
    11 => null 
    12 => null 
    13 => ActionItem {#3205 ▶} 
    14 => null 
    15 => null 
    16 => ActionItem {#3210 ▶} 
    17 => null 
    18 => null 
    19 => ActionItem {#3214 ▶} 
] 

我可以與空住,但我希望能擺脫其中。除了在這種情況下,我期待得到2個空值(一個爲ProjectNotification,另一個用於ProjectBenefit,而我有很多。爲什麼呢?

任何其他意見?

謝謝!

回答

1

我不看不到使用LEFT OUTER JOIN的需要。如果關係是否正確配置,特別是在項目實體,你可以做一個簡單的JOIN和得到不空。

$query = $em->createQuery('SELECT p, pn, pd,pb, pa ' 
     . 'FROM AppBundle:Project p ' 
     . 'JOIN p.notifications pn ' 
     . 'JOIN p.details pd ' 
     . 'JOIN p.benefits pb ' 
     . 'JOIN p.actions pa ' 
     . 'WHERE p.id = :id ') 
     ->setParameter('id', $project->getId()); 
+0

這種解決方案的問題在於,如果關係是OneToOne ,它總是執行一個eage r加載,而不管你指定做延遲加載的事實。所以在這種情況下可以,但是當我爲其他目的檢索項目實體並且加載也是不必要的東西時並不好(細節http://stackoverflow.com/questions/9848747/primary-key-of-owning-side- as-a-join-column/27112833#27112833) –

+0

在我看來,兩個實體之間的關係總是一個事實,所以這個場景應該是使用的標準,並且所有的實體必須具有正確定義的所有關係。您始終可以從數據庫中掌握有關信息的來源。如果你有另一種情況,你只想加載特定的數據,那麼你必須調整你的查詢來做到這一點,並避免使用延遲加載。因此,如果您認爲它不正常,請爲請求較少的數據創建另一個查詢。 – abdiel

+0

這就是問題所在,這不是我執行查詢的問題:你無法控制你得到的東西。在OneToOne關係中(正如我提供的鏈接中詳細解釋的),你沒有選擇:你想要「父母」,它會檢索「孩子」。即使做一個簡單的$ em-> getRepository('AppBundle:Project') - > find($ projectId),你會得到所有OneToOne子項,這是無稽之談。這是我試圖克服的ORM的限制。就我而言,我至少有10個胖子。我被迫檢索超過10次我需要:( –