Tengo algunas clases de modelo de dominio en mi aplicación web que tienen una relación jerárquica con ellas mismas. Un ejemplo de uno es la estructura jerárquica de categorías utilizada para clasificar las publicaciones de los usuarios.EclipseLink @MappedSuperclass y generics
Existe cierta lógica relacionada con la naturaleza jerárquica de estas clases que es común. Así que traté de mover la lógica a una superclase genérica @MappedSuperclass anotada.
Algo así como:
@MappedSuperclass
public abstract class HierarchicalBaseEntity<N extends HierarchicalBaseEntity<N>> extends BaseEntity {
@ManyToOne(optional=true)
@JoinColumn(name="parent")
private N parent;
private int depth;
public N getParent() { ...
public void setParent(N newParent) { ...
public boolean isRoot() { ...
public int getDepth() { ...
public boolean isDescendantOf(N ancestor) { ...
public static <N extends HierarchicalBaseEntity<N>> N getCommonAncestor(N a, N b) { ...
public static <N extends HierarchicalBaseEntity<N>> Collection<N> reduceToCommonAncestors(Collection<N> entities) { ...
}
Las subclases se extienden entonces HierarchicalBaseEntity dando a sí mismos como el tipo genérico N:
@Entity
public class CategoryBean extends HierarchicalBaseEntity<CategoryBean> {
En Java esto todo funciona bastante limpia. Pero, por desgracia EclipseLink no parece que le gusta el campo genérico de 'padre':
private N parent;
Se da la siguiente excepción:
Caused by: Exception [EclipseLink-7250] (Eclipse Persistence Services - 2.1.0.v20100614-r7608): org.eclipse.persistence.exceptions.ValidationException
Exception Description: [class net.timp.yaase.core.model.HierarchicalBaseEntity] uses a non-entity [class java.lang.String] as target entity in the relationship attribute [field parent].
at org.eclipse.persistence.exceptions.ValidationException.nonEntityTargetInRelationship(ValidationException.java:1341)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.RelationshipAccessor.getReferenceDescriptor(RelationshipAccessor.java:416)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOneToOneForeignKeyRelationship(ObjectAccessor.java:609)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOwningMappingKeys(ObjectAccessor.java:678)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor.process(ManyToOneAccessor.java:107)
¿Por qué se quejan de una cadena no entidad?
Como prueba de que he intentado quitar los genéricos y sólo tener el campo primario define como:
private HierarchicalBaseEntity parent;
Sin genéricos, EclipseLink dio esta excepción:
Caused by: Exception [EclipseLink-7250] (Eclipse Persistence Services - 2.1.0.v20100614-r7608): org.eclipse.persistence.exceptions.ValidationException
Exception Description: [class net.timp.yaase.core.model.OnymBean] uses a non-entity [class net.timp.yaase.core.model.HierarchicalBaseEntity] as target entity in the relationship attribute [field parent].
at org.eclipse.persistence.exceptions.ValidationException.nonEntityTargetInRelationship(ValidationException.java:1341)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.RelationshipAccessor.getReferenceDescriptor(RelationshipAccessor.java:416)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOneToOneForeignKeyRelationship(ObjectAccessor.java:609)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOwningMappingKeys(ObjectAccessor.java:678)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor.process(ManyToOneAccessor.java:107)
verdadera HierarchicalBaseEntity no es una Entity en cualquier caso, es una @MappedSuperclass ... pero ¿hay alguna manera de hacer esto con genéricos u otros? Parece que no puedes tener un campo en tu @MappedSuperclass que haga referencia a una de sus subclases.
Esto se ve de alguna manera * similar * a http://forums.sun.com/thread.jspa?threadID=5268944 (pero el problema relacionado es fijo). ¿Podrías probar con otro proveedor? –