EclipseLink @MappedSuperclass和泛型

时间:2010-08-08 19:31:51

标签: java generics 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)

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

3 个答案:

答案 0 :(得分:4)

问题在于,当使用Generics作为关系的字段类型时,EclipseLink在检查实际实例之前无法知道目标类型是什么。因此,必须在运行时动态创建映射,这是不受支持的。

你可以继续使用Generic SuperClass但是这需要将字段移动到它们将定义类型的实体,然后为那些返回Object的字段提供抽象的内部getter / setter,泛型方法会调用这些字符串转换为泛型类型。卷曲但它允许Generic MappedSuperclass。

答案 1 :(得分:1)

我想我已经迟到了,但寻找这个问题答案的人(比如我)应该看看这个: https://bugs.eclipse.org/bugs/show_bug.cgi?id=312132

答案 2 :(得分:-1)

支持持久关系中泛型类型的另一个提供程序是OpenJPA。 OpenJPA的假设是泛型类型字段是持久类型,并使用(OpenJPA特定的)@Type注释进行注释。

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