2012-04-01 18 views
6

Mi piacerebbe mappare un modello di dominio a un database relazionale utilizzando uno dei framework ORM per Java. Sfortunatamente, nessuno di questi sembra avere un supporto adeguato per le classi che implementano più interfacce. Dire che voglio mappare qualcosa di simile:ORM Java: ereditarietà multipla (interfaccia)

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

Quindi quello che sto cercando di realizzare è che un preventivo può fare riferimento a qualsiasi Quotable (azionario, StockIndex e altri), mentre un commerciale può fare riferimento solo entità negoziabili. Ho provato OpenJPA e (semplice) Hibernate senza fortuna anche se il supporto di quest'ultimo per le interfacce sembrava promettente.

C'è qualche framework in grado di gestire il mio scenario? O ci sono dei buoni motivi per cui questo non dovrebbe essere mappato su un database? Se sì, come dovrebbe essere modificato il mio modello?

mio mapping Hibernate iniziale sembrava qualcosa di simile (non sto mostrando alcun roba OpenJPA in quanto non supporta l'ereditarietà di interfaccia o almeno io non riuscivo a capire come):

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

Questo è praticamente identico all'esempio nei Hibernate documentation e risultati in una tabella citabile con un ID e una colonna stringa discriminatore, un tavolo stock_index con un id e l'indice' nome e un tavolo archivio con un id e la nome del titolo. Fin qui tutto bene ...

Ma cosa devo fare con l'interfaccia commerciale? Dovrei impostare una gerarchia separata e mappare azioni in entrambe le gerarchie. Ho provato questo, ma ho dovuto definire diversi nomi di entità per Stock (e necessario includere this patch) ma anche questo non ha funzionato a causa di violazioni di chiave esterna. Ho provato un paio di altre cose oscure che non ha funzionato neanche.

In ogni caso, mappare lo stock due volte non sarebbe una buona soluzione in quanto l'applicazione dovrebbe ricordare di aggiungere istanze di magazzino due volte, una per ogni interfaccia. Preferirei che il framework gestisse questo automatismo.

Idealmente Hibernate permetterebbe di estendere più interfacce, vale a dire qualcosa di simile (si noti l'estende attributo sul sottoclasse elemento):

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

Tutte le altre idee come il mio esempio può essere mappato? Ora ho imparato a conoscere l'elemento <any> che sembra funzioni per me, ma devo ancora comprenderne tutte le implicazioni.

E gli altri quadri? Ho sentito che EclipseLink ha anche qualche supporto per le interfacce, ma non è ben documentato.

+5

Non hai davvero spiegato cosa non funziona o come stai facendo la mappatura. –

+0

Ora ho incluso la mia mappatura di Hibernate con ulteriori dettagli su ciò che ho provato. Spero che ora sia più chiaro. – kaiboy

risposta

3

Non penso che troverete alcun ORM in grado di gestire la gerarchia di interfacce in modo corretto. Quindi non parlerò di ORM qui ma sto per mostrarvi come implementare il vostro esempio usando Qi4j.

Qi4j è un'implementazione di Composite Oriented Programming, che utilizza la piattaforma Java standard e un framework per lo sviluppo di applicazioni incentrate sui domini, inclusi concetti evoluti da AOP, DI e DDD. Vedi http://qi4j.org

In Qi4j, lo stato del dominio viene modellato utilizzando Entità e Valori. Nel seguente esempio di codice presumo che tutto sia un'entità, ma il tuo chilometraggio può variare.

Poiché le entità vengono dichiarate utilizzando solo le interfacce, il caso d'uso deve essere inserito correttamente.

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

È possibile quindi memorizzare tesi in un EntityStore e utilizzare l'API Query per recuperare facilmente (e in modo completamente polimorfica).

Si noti che Qi4j EntityStores non è solo basato su SQL ma supporta anche database NoSQL. Vedere le estensioni disponibili qui: http://qi4j.org/latest/extensions.html

Vedere la documentazione Qi4j se si hanno più domande.

Problemi correlati