2013-01-02 25 views
8

我打算創建我的應用程序,併爲這些模型使用ORM,但問題是,有一部分數據庫使用實體屬性值表。EAV表中的學說ORM

我非常喜歡Doctrine ORM,但我不知道是否有可能創建類似於任何普通教義實體的類,當這個表實際連接到EAV風格時。

對此可以使用Doctrine嗎?如果是這樣,怎麼辦?

+0

開箱即用,我懷疑它。你可能會推出自己的實現。原則是相當可擴展的 – ZolaKt

+0

由於表的關係根據一個值(根據其數據類型加入正確的屬性值表)是不可能的(據我所知),這應該是非常棘手的做到這一點使用Doctrine。 –

回答

4

絕對有可能的:

有這樣的關係: 對象(一對多) - >的AttributeValue - >多對一 - >屬性類型

+1

如果你想獲取某個屬性,你有其他表中的關係,那麼怎麼辦? – Nico

+0

是的,這是個問題 - 幾乎可以肯定唯一的解決方案就是不得不在代碼中使用接口來獲取EAV屬性的屬性,不幸的是,增加了一層複雜性。 –

0

鑑於EAV這似乎是顯而易見的如何構建使用原則的entityattribute之間的關係。在最複雜的情​​況下,我們處理一個Many to Many關係。

因此可以說我們想要將屬性Name映射到實體User。假設用戶只有一個名稱,每個名稱只能屬於一個用戶,則可以使用One to One關係

存檔此鏈接但是如何建模attributevalue之間的關係?問題是值可以是不同類型的,甚至需要不同數量的字段來保存他們的信息。

考慮屬性namephone_number。雖然名稱可能由字符串表示,但電話號碼可能需要整數。或者甚至不僅需要在單獨的字段中提供號碼,還需要區號。

由於EAV需要非常靈活的值表示,因此無法將它們全部存儲在數據庫表中的相同字段中(忽略blob,數據序列化等)。因此,大多數EAV實現使用不同的表來表示不同的值類型。

爲了達到這樣的靈活性,學說特點Inheritance Mapping。它基本上允許你擴展主義實體。這樣做,你的每個子類的實體的指定discriminator

/** 
    * @Entity 
    * @InheritanceType("JOINED") 
    * @DiscriminatorColumn(name="value_type", type="string") 
    * @DiscriminatorMap({"name" = "Name", "phone" = "PhoneNumber"}) 
*/ 
class Value 
{ 
// ... 
} 

/** @Entity */ 
class Name extends Value 
{ 
// ... 
} 

/** @Entity */ 
class PhoneNumber extends Value 
{ 
// ... 
} 

Value類提供了所有共同的價值觀念的實現,即一個ID。每個子類(即NamePhoneNumber)都將這些通用值擴展爲其特定的值,例如附加字段。

  • @DiscriminatorColumn在父關係中定義了一個存儲值的類型的列。
  • 原理使用@DiscriminatorMap將類型從@DiscriminatorColumn映射到其中一個類。

attributevalue之間的關係可以指定給父類。從屬性調用值然後將獲取所有類型的值,這些值可以在運行時使用例如instanceof進行過濾(並處理)。