Mam kilka klas modelu domeny w mojej aplikacji internetowej, które mają hierarchiczną relację do siebie. Przykładem jest hierarchiczna struktura kategorii używana do klasyfikowania postów użytkowników.EclipseLink @MappedSuperclass i generics
Istnieje pewna logika związana z hierarchiczną naturą tych klas, która jest powszechna. Więc próbowałem przenieść logikę do ogólnej nadpisanej adnotacji nadrzędnej klasy @MappedSuperclass.
Coś jak:
@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) { ...
}
podklas następnie rozszerzyć HierarchicalBaseEntity podając się za generycznego typu N:
@Entity
public class CategoryBean extends HierarchicalBaseEntity<CategoryBean> {
W Javie to wszystko działa dość czysto. Ale niestety EclipseLink nie wydaje się podoba generycznym rodzica murawę:
private N parent;
Daje następujący wyjątek:
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)
Dlaczego narzekać String spoza jednostki?
Jako test próbowałem usuwania leków generycznych i tylko o pole rodzic zdefiniowany jako:
private HierarchicalBaseEntity parent;
Bez leków generycznych, EclipseLink dał ten wyjątek:
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)
Prawdziwa HierarchicalBaseEntity Jej nie jest Podmiot w obu przypadkach jest klasą @MappedSuper .. ale czy istnieje sposób, aby to zrobić z rodzajami lub w inny sposób? Wygląda na to, że nie możesz mieć pola w klasie @MappedSuperclass, która odwołuje się do jednej z jego podklasy.
Wygląda to jakoś * podobne * do http://forums.sun.com/thread.jspa?threadID=5268944 (ale powiązany problem został rozwiązany). Czy możesz spróbować z innym dostawcą? –