I have several domain model classes in my web application that are hierarchically related to myself. An example is the hierarchical structure of categories used to classify user messages.
There is some logic related to the hierarchical nature of these classes, which is common. So I tried to move the logic to the general annotated superclass of the @MappedSuperclass class.
Sort of:
@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) { ...
}
Subclasses then extend the HierarchicalBaseEntity, exposing themselves as a generic type N:
@Entity
public class CategoryBean extends HierarchicalBaseEntity<CategoryBean> {
In Java, all this is pretty clean. But unfortunately, EclipseLink does not look like a generic parent field:
private N parent;
This gives the following exception:
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)
Why is he complaining about the non-essence of String?
:
private HierarchicalBaseEntity parent;
generics, EclipseLink :
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)
True HierarchicalBaseEntity - , @MappedSuperclass.. ? , @MappedSuperclass, .