2012-04-01 18 views
6

Chciałbym zmapować model domeny do relacyjnej bazy danych za pomocą jednego z frameworków ORM dla Javy. Niestety, żaden z nich nie wydaje się mieć adekwatnego wsparcia dla klas implementujących wiele interfejsów. Chcę powiedzieć map coś takiego:Java ORM: Wielokrotne dziedziczenie (interfejs)

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; 
} 

Więc co staram się osiągnąć to, że żądanie może odwoływać żadnych quotable (Stock, StockIndex i inne), podczas gdy Transakcja może odwoływać się wyłącznie podmioty zbywalnych. Próbowałem OpenJPA i (zwykły) Hibernate bez powodzenia, mimo że obsługa tych interfejsów wyglądała obiecująco.

Czy istnieją jakieś ramy, które mogą obsłużyć mój scenariusz? Czy istnieją jakieś dobre powody, dla których nie powinno się mapować do bazy danych? Jeśli tak, to w jaki sposób zmodyfikować mój model?

Moja początkowa mapowania Hibernate wyglądał mniej więcej tak (ja nie pokazując żadnych OpenJPA rzeczy, ponieważ nie obsługuje dziedziczenie interfejsu lub przynajmniej nie mogłem dowiedzieć się, w jaki sposób):

<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> 

To jest prawie identyczny przykład w Hibernate documentation i wyniki w tabeli quotable z id i kolumny ciąg dyskryminatora, stół stock_index z identyfikatorem oraz indeksu”nazwy i stół magazynie z identyfikatorem a nazwa akcji. Do tej pory tak dobrze ...

Co jednak powinienem zrobić z interfejsem Tradeable? Musiałbym ustawić oddzielną hierarchię i zapasy map w obu hierarchiach. Próbowałem tego, ale musiałem zdefiniować różne nazwy jednostek dla Stock (i musiałem dodać this patch), ale to też nie zadziałało z powodu naruszenia klucza obcego. Wypróbowałem kilka innych niejasnych rzeczy, które też nie działały.

W każdym razie dwukrotne odwzorowanie zapasów nie byłoby dobrym rozwiązaniem, ponieważ aplikacja musiałaby pamiętać, dodając instancje magazynowe dwukrotnie - raz dla każdego interfejsu. Wolałbym, aby framework obsługiwał to automatycznie.

Idealnie hibernacji pozwoli rozszerzenie wiele interfejsów, czyli coś jak (należy zwrócić uwagę na rozciąga atrybut na podklasy elementu):

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

jakieś inne pomysły jak mój przykład można odwzorować? Dowiedziałem się już o elemencie <any>, który wygląda na to, że może działać dla mnie, ale muszę jeszcze zrozumieć wszystkie jego implikacje.

Co powiesz na inne frameworki? Słyszałem, że EclipseLink ma również wsparcie dla interfejsów, ale nie jest dobrze udokumentowany.

+5

Tak naprawdę nie wyjaśniłeś, co nie działa lub jak wykonujesz mapowanie. –

+0

Mam teraz dołączone moje mapowanie Hibernacji z bardziej szczegółowymi informacjami o tym, co wypróbowałem. Mam nadzieję, że teraz staje się bardziej przejrzysta. – kaiboy

Odpowiedz

3

Nie sądzę, że można znaleźć ORM w stanie ładnie poradzić sobie z hierarchią interfejsów. Nie będę tu mówił o ORM, ale zamierzam pokazać, jak zaimplementować twój przykład za pomocą Qi4j.

Qi4j to implementacja programowania zorientowanego na kompozyt, przy użyciu standardowej platformy Java i platformy do projektowania aplikacji opartych na domenach, w tym rozwiniętych koncepcji z AOP, DI i DDD. Zobacz http://qi4j.org

W Qi4j, stan domeny jest modelowany za pomocą elementów i wartości. W poniższym przykładzie kodu zakładam, że wszystko jest Entity, ale twój przebieg może się różnić.

Ponieważ encje są deklarowane przy użyciu tylko interfejsów, Twój przypadek użycia powinien pasować ładnie.

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

Następnie można tez przechowywać w EntityStore i użyć API Query pobrać je łatwo (i w pełni polimorficznych sposób).

Należy pamiętać, że Qi4j EntityStores są oparte nie tylko na języku SQL, ale obsługują również bazy danych NoSQL. Zobacz dostępne rozszerzenia tutaj: http://qi4j.org/latest/extensions.html

Zobacz dokumentację Qi4j, jeśli masz więcej pytań.

Powiązane problemy