2010-08-08 41 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;我在這裏再次引用它並不是爲了自我推銷,而是希望它可能指示一些途徑支持泛型樹,而不必將具體類型信息向下壓入類型層次結構(從而失去了泛型類型模型的本質)。