2010-08-08 44 views
5

我在我的web应用程序中有几个领域模型类与他们自己有层次关系。一个例子是用于分类用户发布的分层结构类别结构。EclipseLink @MappedSuperclass和泛型

有一些常见的与这些类的层次性有关的逻辑。所以我试图将逻辑移入一个通用的@MappedSuperclass注解的超类。

喜欢的东西:

@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) { ... 
} 

子类,然后扩展HierarchicalBaseEntity给自己的泛型类型N:

@Entity 
public class CategoryBean extends HierarchicalBaseEntity<CategoryBean> { 

在Java这一切工作了相当干净。但不幸的是EclipseLink的似乎并不像一般的“父”字段:

private N parent; 

它提供了以下异常:

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) 

为什么抱怨非实体的字符串?

作为测试我试图消除仿制药,只是有父字段定义为:

private HierarchicalBaseEntity parent; 

没有泛型,的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) 

真HierarchicalBaseEntity它不是一个在任何情况下,实体是一个@MappedSuperclass ..但有没有办法用泛型或其他方式做到这一点?看起来您的@MappedSuperclass中没有引用其子类的字段。

+0

这看起来与http://forums.sun.com/thread.jspa?threadID=5268944相似*,但相关问题已修复。你可以尝试与另一个提供商? – 2010-08-08 22:52:24

回答

3

问题是,当使用泛型作为关系的字段类型时,EclipseLink无法知道目标类型是什么,直到运行时检查实际实例。所以映射必须在运行时动态创建,并且不支持。

您可以继续使用Generic SuperClass,但这需要将字段移动到实体中,在那些实体中定义了类型,然后为那些返回Object的字段提供抽象内部getter/setter,泛型方法将调用cast泛型类型。卷积,但它将允许通用MappedSuperclass。

+0

嗨戈登, 感谢您的回答。我会尝试将字段放在子类中的建议。我可以看到它是如何工作的。 我目前有一个HierarchicalEntity接口和一个静态的'helper'类,其中的逻辑是Works,但它并不像我想的那么干净。我想知道是否可以使用@AssociationOverride以某种方式重新定义关联。 – 2010-08-09 15:17:05

+0

不幸的是,在这种情况下,问题与属性类型有关。 @AssociationOverrides用于更改数据库信息,但没有用于指定目标类型的属性。 – 2010-08-10 13:02:54

+0

嗨Gordon,我找不到比您建议用抽象获取者实现一个超类的公共逻辑更清晰的解决方案。所以你得到我的投票。 BTW。你知道这是否可以在其他JPA实现中使用,或者它是否是JPA规范的一部分? – 2010-08-18 14:10:20

-1

支持在持久性关系泛型类型其他提供商OpenJPA 。 OpenJPA做出的假设是泛型类型字段是一个持久类型,并且用(OpenJPA特定的)@Type注释来注释。

此@Type注释充当OpenJPA映射引擎的占位符,并保存一个映射,其中引用是运行时实例的持久标识。很多年前,我写了一个blog;我在这里再次引用它并不是为了自我推销,而是希望它可能指示一些途径支持泛型树,而不必将具体类型信息向下压入类型层次结构(从而失去了泛型类型模型的本质)。