2011-12-13 42 views
18

我有一個DQL查詢和實體專業化的問題。Doctrine DQL,類表繼承和訪問子類字段

我有一個實體叫Auction,這是OneToOneItem的關係。 ItemFilmBookmappedSuperclass。我需要一個可以支持搜索引擎的查詢,允許用戶查找具有不同屬性的不同屬性AND的拍賣(這是AND部分,使其具有挑戰性)。

問題是,即使Auction有一個指向Item的關聯,我需要訪問FilmBook特定的字段。用戶將指定他們正在查找的Item類型,但除了在我的DQL查詢中使用INSTANCE OF之外,我沒有看到任何使用此信息的方式。

到目前爲止,我使用查詢像曾嘗試:

SELECT a FROM Entities\Auction a 
    INNER JOIN a.item i 
    INNER JOIN i.bookTypes b 
    WHERE i INSTANCE OF Entities\Book 
    AND b.type = 'Fantasy' 
    AND ...". 

這樣一個錯誤的查詢結果說:

Entities\Item沒有字段或協會命名bookTypes

這是虛假的Book,但真的Item

我也曾嘗試

SELECT a FROM Entities\Book i 
    INNER JOIN i.auction a ... 

不過,我想學說規定,我指的是同一個實體在SELECTFROM語句。

如果這很重要,我使用類表繼承。儘管如此,我認爲切換到單表繼承是不可能的。

任何想法?

+0

可能重複[where-ing歧視表](http://stackoverflow.com/questions/14851602/where-ing-in-discriminated-tables) – Ocramius 2014-01-20 05:57:10

回答

9

正如馬特所說,這是一個老教義項目不能解決的問題(DDC-16)。

問題是,學說的DQL是一個靜態類型的語言,它的內部具有一定的複雜性。

我們考慮過允許多次上傳,但努力獲得這個工作根本不值得,而且人們會濫用語法做非常危險的事情。

如DDC-16所述,也不可能理解屬性屬於哪個類而不會產生討厭的問題,例如多個子類使用不同的列名定義相同的屬性。

如果要過濾CTI或JTI中的子類中的數據,可以使用我在https://stackoverflow.com/a/14854067/347063中描述的技術。這會將您的DQL與所有涉及的子類聯繫起來。

的DQL你需要在你的情況下,最有可能(假設Entities\BookEntities\Item子類):

SELECT 
    a 
FROM 
    Entities\Auction a 
INNER JOIN 
    a.item i 
INNER JOIN 
    i.bookTypes b 
WHERE 
    i.id IN (
     SELECT 
      b.id 
     FROM 
      Entities\Book b 
     WHERE 
      b.type = 'Fantasy' 
    ) 

那是你的問題的僞代碼。這並不好,但請記住,SQL和DQL是非常不同的,並遵循不同的規則。

0

我有同樣的問題,並沒有找到一個解決方案,沒有使用每個子類的單獨的查詢,並稍後在應用程序級別合併它們。

有一點我確定,單表繼承不會解決這個問題,完全一樣的事情。

還有另一種選擇,雖然在邏輯上很髒。 定義超類中的所有字段(您需要的字段)。如果記錄邏輯上沒有該字段,它將是空的。不是一個漂亮的景象,但嘿,比2-3-4 -...查詢更優化。此外,在這種情況下單表繼承絕對是更好的方式去

+2

合併結果並不完全如此,因爲我從不需要Films和Books同時出現在查詢結果中。我終於提出的解決方法是添加拍賣 - 項目關係的反面並查詢項目而不是拍賣('SELECT i FROM Entities \ Book INNER JOIN i.auction a WHERE(...)') 。由於我知道我在找哪個子類,所以我可以相應地構建我的查詢。但是,感謝你的回覆,你的想法可能是一個好的方法,因爲在這樣的情況下,使用繼承與Doctrine似乎沒什麼意義。 – crizzis 2011-12-26 23:05:11

2

教義團隊已經表示,他們不會增加對這種支持:

http://www.doctrine-project.org/jira/browse/DDC-16

中肯的意見從該頁面:

這確實很棘手。然而,這種語法本身可以不起作用, ,因爲可能有幾個子類名爲「d」, ,所以教義不會知道你的意思。


我關閉這一個。

這個問題的要求基本上是違反面向對象的原則。

如果你真的需要在您的 繼承跨多個孩子的實體進行過濾,然後嘗試的東西如下代替:

選擇 [R FROM 根r其中 r.id IN( 選擇 ℃。 ID FROM Child C級 WHERE c.field =:值 )

2

您可以輕鬆地解決這個左連接使用的ID與你的繼承類的基礎機構:

SELECT a FROM Entities\Auction a 
    INNER JOIN a.item i 
    INNER JOIN Entities\Book b WITH b.id = i.id 
    INNER JOIN b.bookTypes bt 
    WHERE bt.type = 'Fantasy' 
    AND... 

或用的QueryBuilder:

$queryBuilderb->select('a') 
    ->from('Entities\Auction', 'a') 
    ->innerJoin('a.item', 'i') 
    ->innerJoin('Entities\Book', 'b', 'WITH', 'b.id = i.id') 
    ->innerJoin('b.bookTypes', 'bt') 
    ->where('bt.type = :type') 
    ->andWhere(... 
    ->setParameter('type', 'Fantasy'); 

這是根據給出的答案由伊恩飛利浦在這個問題here