2012-04-01 17 views
6

Me gustaría asignar un modelo de dominio a una base de datos relacional utilizando uno de los marcos ORM para Java. Desafortunadamente, ninguno de ellos parece tener soporte adecuado para las clases que implementan múltiples interfaces. Digamos que quiero para mapear algo como:Java ORM: Herencia múltiple (interfaz)

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

Así que lo que estoy tratando de lograr es que una cita se puede hacer referencia a cualquier Quotable (Stock, StockIndex y otros), mientras que un comercio sólo puede hacer referencia a las entidades negociables. Intenté con OpenJPA y Hibernate (sencillo) sin suerte, aunque el soporte de las últimas para las interfaces parecía prometedor.

¿Hay algún marco que pueda manejar mi situación? ¿O hay alguna buena razón por la cual esto no se debe asignar a una base de datos? De ser así, ¿cómo debería modificarse mi modelo?

Mi mapeo inicial de hibernación parecía algo como esto (no estoy mostrando ninguna materia OpenJPA ya que no soporta la herencia de interfaces o al menos yo no pude averiguar cómo):

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

Este es prácticamente idéntico al ejemplo de las Hibernate documentation y resultados en una tabla citable con un ID y una columna de cadena discriminador, una mesa stock_index con un ID y el nombre de índice' y una acción tabla con un ID y la el nombre de la acción Hasta ahora todo bien ...

Pero, ¿qué debo hacer con la interfaz Tradeable? Tendría que configurar una jerarquía separada y asignar Stock en ambas jerarquías. Intenté esto, pero tuve que definir diferentes nombres de entidad para Stock (y necesité incluir this patch) pero esto tampoco funcionó debido a violaciones de clave foránea. Probé un par de otras cosas oscuras que tampoco funcionaron.

De todos modos, mapear Stock dos veces no sería una buena solución ya que la aplicación tendría que recordar agregar instancias Stock dos veces, una para cada interfaz. Prefiero que el framework maneje esto automáticamente.

Idealmente Hibernate permitiría extender múltiples interfaces, es decir, algo así como (nótese el extiende atributo en el elementosubclase):

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

Cualquier otra idea de cómo mi ejemplo se pueden asignar? Ahora he aprendido sobre el elemento <any> que parece que podría funcionar para mí, pero aún no he entendido todas sus implicaciones.

¿Qué hay de otros marcos? Escuché que EclipseLink también tiene algo de soporte para las interfaces, pero no está bien documentado.

+5

No ha explicado realmente lo que no funciona o cómo está haciendo la asignación. –

+0

Ahora he incluido mi mapeo de Hibernate con más detalles sobre lo que probé. Espero que se vuelva más claro ahora. – kaiboy

Respuesta

3

No creo que encuentre ningún ORM capaz de manejar bien la jerarquía de interfaces. Así que no hablaré sobre los ORM aquí, pero les mostraré cómo implementar su ejemplo usando Qi4j.

Qi4j es una implementación de Programación Orientado a Composite, que utiliza la plataforma Java estándar y un marco para el desarrollo de aplicaciones centradas en el dominio, que incluye conceptos evolucionados de AOP, DI y DDD. Consulte http://qi4j.org

En Qi4j, el estado del dominio se modela mediante Entidades y valores. En el siguiente ejemplo de código, supongo que todo es una Entidad, pero su kilometraje puede variar.

Como las entidades se declaran utilizando solo interfaces, su caso de uso debería encajar perfectamente.

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

A continuación, puede tesis Almacenar en un EntityStore y utilizar la API Query para recuperar fácilmente (y de una manera totalmente polimórfica).

Tenga en cuenta que Qi4j EntityStores no solo está basado en SQL sino que también admite bases de datos NoSQL. Vea las extensiones disponibles aquí: http://qi4j.org/latest/extensions.html

Consulte la documentación de Qi4j si tiene más preguntas.