2012-04-01 74 views
6

我想使用Java的一個ORM框架將域模型映射到關係數據庫。不幸的是,他們沒有一個似乎對實現多接口的類有足夠的支持。說我要地圖是這樣的:Java ORM:多個(接口)繼承

public interface Quotable { 
} 

public interface Tradable { 
} 

// StockIndex only implements Quotable as it cannot be trade directly 
public class StockIndex implements Quotable { 
} 

// Stock implements both interfaces as there are market quotes and can be traded 
public class Stock implements Quotable, Tradable { 
} 

public class Quote { 
    private Quotable quotable; 
} 

public class Trade { 
    private Tradable tradable; 
} 

所以我想要實現的是一個報價可以引用任何新書(股票,StockIndex等),而貿易只能引用可交易的實體。儘管後者對界面的支持看起來很有希望,但我已經嘗試過OpenJPA和(普通)Hibernate,但沒有運氣。

有沒有任何框架可以處理我的情況?或者有沒有什麼理由不把它映射到數據庫?如果是這樣,我的模型應該如何修改?

我最初的Hibernate映射看起來是這樣的(我沒有表現出任何OpenJPA的東西,因爲它不支持接口繼承或至少我無法弄清楚如何):

<hibernate-mapping package="com.foo"> 
    <class name="Quotable" table="quotable" > 
     <id type="java.lang.Long" column="id"> 
      <generator class="sequence" /> 
     </id> 

     <discriminator column="type" type="string" /> 

     <subclass name="StockIndex"> 
      <join table="stock_index" > 
       <key column="id"/> 
       <property name="name" column="name" access="field" /> 
      </join> 
     </subclass> 

     <subclass name="Stock"> 
      <join table="stock" > 
       <key column="id"/> 
       <property name="name" column="name" access="field" /> 
      </join> 
     </subclass> 
    </class> 
</hibernate-mapping> 

這是幾乎等同於在Hibernate documentation並導致表新書一個id和一個字符串鑑別列,表stock_index一個ID和索引的名字和一張桌子股票有id和例子股票的名稱。到目前爲止這麼好...

但我該怎麼處理可交易界面?我將不得不在兩個層次結構中設置單獨的層次結構並映射庫存。我嘗試過,但必須爲庫存定義不同的實體名稱(並且需要包含this patch),但由於外鍵違規,這也不起作用。我嘗試了其他一些晦澀難懂的事情,但都沒有奏效。

無論如何,映射兩次股票不會是一個好的解決方案,因爲應用程序必須記住兩次添加庫存實例 - 每個接口一次。我寧願讓框架自動處理。

理想的Hibernate將允許(在元素注意延伸屬性)延伸的多個接口,即是這樣的:

<subclass name="Stock" extends="Quotable, Tradable" > 
    <join table="stock" > 
     <key column="id"/> 
     <property name="name" column="name" access="field" /> 
    </join> 
</subclass> 

任何其他的想法我的例子可以如何映射?我現在瞭解到<any>這個元素看起來可能適合我,但我還沒有理解它的所有含義。

其他框架如何?我聽說EclipseLink也有一些接口的支持,但沒有很好的文檔。

+5

你還沒有真正解釋什麼不起作用,或者你如何進行映射。 – 2012-04-01 21:52:12

+0

我現在已經包含了我的Hibernate映射關於我試用的更多細節。希望它現在變得更加清晰。 – kaiboy 2012-04-02 19:35:20

回答

3

我不認爲你會發現任何ORM能夠很好地處理接口層次結構。 所以我不會在這裏討論ORM,但我會告訴你如何使用Qi4j實現你的例子。使用標準Java平臺和以域爲中心的應用程序開發框架,包括AOP,DI和DDD的演進概念。Qi4j是一個面向組合編程的實現,請參閱http://qi4j.org

在Qi4j中,域狀態使用實體和值建模。在下面的代碼示例中,我假設一切都是實體,但是您的里程可能會有所不同。

由於實體僅使用接口聲明,所以您的用例應該很好地適用。

interface Quotable { ... } 
interface Tradable { ... } 
interface StockIndex extends Quotable { ... } 
interface Stock extends Quotable, Tradable { ... } 
interface Quote { 
    Association<Quotable> quotable(); 
} 
interface Trade { 
    Association<Tradable> tradable(); 
} 

然後,您可以儲存論文在EntityStore和使用查詢API輕鬆地檢索它們(和完全多態的方式)。

請注意,Qi4j EntityStores不僅基於SQL,而且還支持NoSQL數據庫。請參閱此處的可用擴展名:http://qi4j.org/latest/extensions.html

如果您有更多問題,請參閱Qi4j文檔。