Ho alcune classi di modelli di dominio nella mia app Web che hanno una relazione gerarchica con se stessi. Un esempio di uno è la struttura gerarchica delle categorie utilizzata per classificare i messaggi degli utenti.EclipseLink @MappedSuperclass e generici
C'è una logica relativa alla natura gerarchica di queste classi che è comune. Così ho provato a spostare la logica in una generica superclasse annotata @MappedSuperclass.
Qualcosa di simile:
@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) { ...
}
Le sottoclassi poi si estendono HierarchicalBaseEntity dando se stessi come il tipo generico N:
@Entity
public class CategoryBean extends HierarchicalBaseEntity<CategoryBean> {
In Java questo funziona tutto molto pulito. Ma purtroppo EclipseLink non sembra piacere il 'genitore' campo generico:
private N parent;
Dà la seguente eccezione:
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)
Perché è lamentano una stringa non-entità?
Come test ho provato a rimuovere i farmaci generici e solo per avere il campo genitore definito come:
private HierarchicalBaseEntity parent;
Senza farmaci generici, EclipseLink ha dato questa eccezione:
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)
vero HierarchicalBaseEntity suo non è un Entity in entrambi i casi, è @MappedSuperclass .. ma c'è un modo per farlo con i generici o in altro modo? Sembra che tu non possa avere un campo nella tua @MappedSuperclass che fa riferimento a una delle sue sottoclassi.
Questo sembra in qualche modo * simile * a http://forums.sun.com/thread.jspa?threadID=5268944 (ma il problema correlato è stato risolto). Potresti provare con un altro fornitore? –