2010-05-11 11 views
8

tengo una clase genérica que es también un super clase asignada que tiene un campo privado que mantiene un puntero a otro objeto del mismo tipo:Cómo manejar las anotaciones JPA para un puntero a una interfaz genérica

@MappedSuperclass 
public abstract class MyClass<T extends MyIfc<T>> 
    implements MyIfc<T> 
    { 

     @OneToOne() 
     @JoinColumn(name = "previous", nullable = true) 
     private T previous; 

      ... 
      } 

Mi problema es que Eclipse está mostrando un error en el archivo en la "entidad de destino" T de OneToOne porque "anterior no es una entidad". Todas las implementaciones de MyIfc son, de hecho, Entidades. También debo agregar que cada implementación concreta que hereda de MyClass usa un valor diferente para T (porque T es ella misma), así que no puedo usar el atributo "targetEntity".

Supongo que si no hay respuesta, tendré que mover esta anotación JPA a todas las subclases concretas de MyClass. Simplemente parece como que JPA/Hibernate debería ser lo suficientemente inteligente como para saber que todo funcionará en tiempo de ejecución. Me hace preguntar si debería ignorar este error de alguna manera.

Respuesta

8

Mi problema es que Eclipse está mostrando un error en el archivo en el OneToOne "entidad de destino 'T' para el anterior no es una entidad".

Sí, e incluso si T estaba extendiendo una Entity, que no estoy al tanto de cualquier proveedor JPA apoyar esta (eso no es parte de la especificación JPA de todos modos). Para obtener más retroalimentación echar un vistazo a JPA Generic entities classes Mappedsuperclass are not possible! (hilo muy similar sobre EclipseLink):

Sin usted no será capaz de hacer las Entidades genérico. El proveedor no podrá asignar la relación al tipo específico definido por la definición genérica, ya que este tipo se asigna cuando la entidad se crea en código, no donde se define la entidad. Recuerde que al designar genéricos, la recopilación (en este caso) está limitada solo a esos tipos. El proveedor no puede ser tan restrictivo por instancia de entidad. En algunos casos, cambiar el tipo puede dar como resultado el mapeo de tablas completamente diferentes para una sola instancia de Entity y eso definitivamente no es compatible.

+0

Gracias por lo que confirma que esto es imposible. Otra razón más por la que la herencia de implementación nunca funciona de la manera que desea. Eliminaré todas las referencias a tipos genéricos de la superclase abstracta y los duplicaré en todas las implementaciones concretas. Me pregunto si hubiera sido mejor usar archivos de mapas XML en lugar de anotaciones. – HDave

+0

@HDave No * creo * que esto cambiaría nada, espero que su proveedor de JPA se queje en el tiempo de ejecución. –

+0

Incluso si no lo hiciera, supongo que las relaciones entre entidades de tipo seguro y tipo compilación valen la tranquilidad.¡Apesta que tengo que pasar hoy copiando este fragmento de código en 17 implementaciones de entidades concretas! – HDave

2

Desde JDO es compatible con la persistencia de campos de interfaz (que es un concepto similar a lo que tenemos aquí), y desde DataNucleus APP se construye en la parte superior de las capacidades de JDO, entonces es probable que le permitiría a persistir un campo tan (Tengo un ejemplo usando JDO que hace algo muy similar, pero sin ver los restos de tus clases y el código de persistencia es imposible que sea definitivo). Dale una oportunidad y mira lo que pasa.

Obviamente esto es más allá de la especificación JPA, por lo tanto, si la portabilidad es una preocupación para usted entonces tiene una primera piensan

+0

De hecho, también lo probé con JPA y eso también funciona. Entonces no, no es imposible, como está implícito en la otra respuesta. Está más allá de la especificación JPA sin duda, pero es muy posible. Solo necesita usar DataNucleus – DataNucleus

1

se puede añadir un @OneToOne (targetEntity = SuperClassOfT.class) a los campos para hacer este trabajo.

La hora de salida How to implement polymorphic JPA entities with generic relations

+0

Este simple truco solo funciona cuando la jerarquía que comienza desde SuperClassOfT se correlaciona con una estrategia de tabla única. Para tomar el ejemplo en su enlace, siempre que todas las subclases de Evento estén mapeadas en la tabla de eventos, puede indicar a Hibernate que use Evento como objetivo y esto implicará usar la tabla de eventos para almacenar/buscar todas las instancias de destino. Pero si, por ejemplo, desea asignar UserEvent y ApplicationEvent en tablas diferentes, no creo que la solución que proponga funcione. – zakmck

+0

Supongo que la estrategia de tabla unida también podría funcionar, más o menos de la misma manera que lo hace la tabla única, pero no estoy seguro. – zakmck

+0

@zakmck - ¡ese es un excelente punto! No estoy seguro de cómo hibernate maneja las uniones en superclases cuando se usa una estrategia de tabla por clase. Dicho esto, la información genérica solo se relaciona con las clases de Java, la otra restricción de la que usted habla todavía existiría sin usar genéricos y, en cambio, depende de conversiones explícitas. – logan

Cuestiones relacionadas