[英]Java: Generics, superclass type reference pointing to <? extends superclass> type reference
[英]Is it possible to map (JPA) a Java type hierarchy that uses generics in the abstract superclass?
我一直在閱讀很多關於JPA映射的SO問題和博客文章和文檔,但似乎沒有什么能清楚地解決我的情況(這讓我感到驚訝,因為我確信我不是第一個想要映射類層次結構的人像這樣)。
我有一個很好的,設計干凈的對象模型,我需要通過JPA映射。 它如下
public abstract class BaseEntity<T extends BaseEntity> {
private Integer id;
private List<T> children;
}
public class ConcreteEntity1 extends BaseEntity<ConcreteEntity2> {
private String value;
}
public class ConcreteEntity2 extends BaseEntity{
private String foo;
}
我似乎無法將其映射到地圖上。 我得到的最接近的是這樣的(我現在正在使用XML映射,雖然我也嘗試過注釋):
<mapped-superclass class="com.me.datamodel.BaseEntity" access="FIELD">
<attributes>
<id name="id">
<column name="auto_id" nullable="false"/>
<generated-value strategy="IDENTITY"/>
</id>
</attributes>
</mapped-superclass>
<entity class="com.me.datamodel.ConcreteEntity1" access="FIELD">
<attributes>
<basic name="value" />
<one-to-many name="children" fetch="EAGER" mapped-by="media">
<cascade><cascade-all /></cascade>
</one-to-many>
</attributes>
</entity>
<entity class="com.me.datamodel.ConcreteEntity2" access="FIELD">
<attributes>
<basic name="foo" />
</attributes>
</entity>
這個問題是JPA抱怨ConcreteEntity1
的children
映射。 它聲稱children
的目標實體(BaseEntity)不是實體。 嗯,這是正確的,'BaseEntity'不是一個實體。 但實際的children
類型不是 BaseEntity
而是ConcreteEntity2
(由ConcreteEntity1
的類型參數聲明)。
那么如何映射這樣的對象模型呢? 我已經嘗試了很多變化但沒有工作(它們都在實體管理器初始化期間失敗)。
我認為你幾乎所有東西都是正確的,除了在ConcreteEntity2
正確擴展BaseEntity
:你忘了說像public class ConcreteEntity2 extends BaseEntity<ConcreteEntity2> {...}
這樣的類型參數public class ConcreteEntity2 extends BaseEntity<ConcreteEntity2> {...}
。 因此,它無法映射ConcreteEntity2
,因此無法映射ConcreteEntity1
。
所以我的工作代碼(使用EclipseLink 2.5.1和Hibernate 4.3.1.Final測試):
@MappedSuperclass
public abstract class BaseEntity<T extends BaseEntity> {
private Integer id;
private List<T> children;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@OneToMany(cascade=CascadeType.ALL)
public List<T> getChildren() {
return children;
}
public void setChildren(List<T> children) {
this.children = children;
}
}
@Entity
public class ConcreteEntity1 extends BaseEntity<ConcreteEntity2> {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@Entity
public class ConcreteEntity2 extends BaseEntity<ConcreteEntity2> {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
一些重要的注意事項:在JPA嘗試映射的每個實體中,如果持久字段是一個集合,那么它必須是實體類型的集合(JPA規范第2.2章持久字段和屬性 )。 如果您不知道ConcreteEntity2
的子BaseEntity
究竟是什么(除了它們是BaseEntity
),您必須使BaseEntity
成為實體,或者引入另一個實體以由所有可能的子類擴展並使用它。 在上述任何一種情況下,您都必須使用JPA繼承。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.