我目前正在爲遺留數據庫(大量複合鍵和單列鍵)定義JPA實體。我創建了以下實體超:JPA(Hibernate):在通用@MappedSuperclass中使用@EmbeddedId時出錯
@MappedSuperclass
public abstract class AbstractEntity<ID extends Serializable> {
public abstract ID getId();
public abstract void setId(ID id);
}
然後對組合鍵的超類(以及長期主鍵的超類,不在此列):
@MappedSuperclass
public abstract class AbstractEmbeddedIdEntity<ID extends Serializable> extends AbstractEntity<ID> {
@EmbeddedId
private ID id;
public AbstractEmbeddedIdEntity() {
id = newId();
}
@Override
public ID getId() {
return id;
}
@Override
public void setId(ID id) {
this.id = id;
}
protected abstract ID newId();
}
最後具體的實體,如這樣的:
@Entity
@Table(name = "firstEntity")
public class FirstEntity extends AbstractEmbeddedIdEntity<FirstEntityId> {
public FirstEntity() {
}
@Embeddable
public static class FirstEntityId implements Serializable {
@Column(name = "firstId")
private String firstId;
public FirstEntityId() {
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof FirstEntityId)) {
return false;
}
FirstEntityId other = (FirstEntityId) obj;
return
Objects.equals(firstId, other.firstId);
}
@Override
public int hashCode() {
return Objects.hash(firstId);
}
}
@Override
protected FirstEntityId newId() {
return new FirstEntityId();
}
}
現在的問題是,如果我有多個實體這樣並嘗試訪問一個實體(當前Spring引導,例如的ID屬性),拋出一個異常:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [firstId] on this ManagedType [unknown]
我已經調試這一點,並發現,在休眠,元我所有的實體映射到同一MappedSupperclass實例。在應用程序啓動期間,由newId()
返回的@EmbeddedId
被設置爲MappedSupper類,覆蓋前一個實體的ID。所以最後,所有實體都映射到相同的MappedSupper類,但MappedSupper類只有最後一個實體的@EmbeddedId
。
在上例中,訪問ID屬性失敗,因爲最後一個實體的@EmbeddedId
沒有名爲「firstId」的屬性(它已被最後一個實體的ID屬性覆蓋)。
現在我想知道如果我的方法是錯誤的,如果我失去了一些東西,或者這可能是一個與休眠問題?
使用彈簧靴的完整示例available on github。以mvn spring-boot:run
運行。
我認爲在涉及到JPA/Hibernate映射時最好不要使用任何抽象類,除非涉及到超類,它的繼承含義。事實上,'@ MappedSuperclass'用於繼承,因此意味着擴展它的不同類之間的巨大鏈接。 你可能應該用最簡單的方法逐一映射它們,所以它們與你的AbstractEntity類沒有關係。 – DamCx
你的意思是'我所有的實體指向他們的MappedSupperclass的同一個實例'? Java中沒有'指向普通超類對象的指針'。另外,如果我是你,我會避免使用內部類作爲可嵌入的 – crizzis
@crizzis:我已更新我的問題並修復了不正確的部分,謝謝指出。實際上,hibernate元模型將我所有的實體映射到相同的MappedSupperclass實例。另外,爲什麼你會避免使用內部類作爲嵌入式? – Dominic