2010-10-30 116 views
1

鑑於下面的例子(部門 - 項目):使用具有*嵌套*複合主鍵的@IdClass限制JPA 1.0?

甲系具有下列特性(複合主鍵):

@Entity 
@IdClass(DeptId.class) 
public class Department 
{ 
    @Id 
    @Column(name="number") 
    private Integer number; 

    @Id 
    @Column(name="country") 
    private String country; 

    @Column(name="name") 
    private String name; 

    @OneToMany(mappedBy="dept") 
    private Collection<Project> projects; 

    ... 
} 

這裏的PK類:

public class DeptId implements Serializable 
{ 
    private Integer number; 
    private String country; 

    ... 
} 

之間的關係項目和部門是多對一的,這是一個設施可以有很多項目。 Project類本身使用引用Department組合鍵的組合鍵。重要提示:這只是關於@IdClass而不是@EmbeddedId的實現。

然後(有問題的)JPA 1.0 @IdClass實施將不得不尋找類似的東西(冗餘deptNum和deptCtry屬性): - 一個部門

@Entity 
@IdClass(ProjectId.class) 
public class Project 
{ 
    @Id 
    @Column(name="dept_number") 
    private Integer deptNumber; 

    @Id 
    @Column(name="dept_country") 
    private String deptCountry; 

    @Id 
    @Column(name="name") 
    private String name; 

    @ManyToOne 
    @JoinColumns({ 
     @JoinColumn(name="dept_number", referencedColumnName="number"), 
     @JoinColumn(name="dept_country", referencedColumnName="country") 
    })  
    private Department dept; 

    ... 
} 

的專案編號是內>這只是一個唯一的名稱:

public class ProjectId implements Serializable 
{ 
    private String name; 
    private DeptId dept; 

    ... 
} 

這樣做的問題是,無論是休眠還是EclipseLink的知道如何將兩個冗餘特性deptNum和deptCtry在項目映射到DEPTID的部門屬性(或其中的性的判定)。 - > MappingException等

我的問題是:

這是JPA 1.0的限制,與複合鍵的表引用其它組合鍵使用@IdClass實現一般不會工作,因爲JPA實現根本無法知道如何映射這些字段?

作爲一種解決方法,您必須對這些類使用@EmbeddedId,或者使用JPA 2.0語法來使用@Id註釋@XToX關聯。我只是想確保我對此的看法是正確的。

感謝

回答

2

的問題張貼的代碼是,JPA 1.0真的不允許複合主鍵類的嵌套。這個專案編號無效:

public class ProjectId implements Serializable 
{ 
    private String name; 
    private DeptId dept; 

    ... 
} 

DEPTID已被壓扁,如:

public class ProjectId implements Serializable 
{ 
    private Integer deptNumber; 
    private String deptCountry; 
    private String name; 

    ... 
} 

我剛收到的EclipseLink版本去,但是Hibernate有與問題。我想知道如何告訴Hibernate假設JPA 1.0。

2

這樣做的問題是,無論是休眠還是EclipseLink的知道如何在DEPTID

兩個 冗餘性能deptNum和deptCtry在項目映射到部門財產

這是爲什麼需要使用這種映射將ManyToOne外鍵定義爲只讀。這通過將JoinColumn屬性insertableupdatable設置爲false來完成。

所以請嘗試以下操作:

@Entity 
@IdClass(ProjectId.class) 
public class Project 
{ 
    @Id 
    @Column(name="dept_number") 
    private Integer deptNumber; 

    @Id 
    @Column(name="dept_country") 
    private String deptCountry; 

    @Id 
    @Column(name="name") 
    private String name; 

    @ManyToOne 
    @JoinColumns({ 
     @JoinColumn(name="dept_number", referencedColumnName="number", insertable=false, updatable=false), 
     @JoinColumn(name="dept_country", referencedColumnName="country", insertable=false, updatable=false) 
    })  
    private Department dept; 
    ... 
} 
+0

這不關於可插入/可更新的東西。 ORM如何知道ProjectId的dept_x映射的屬性?我沒有與兩個工作...休眠和EL。當EntityManagerFactory被實例化時,它們已經失敗。這是有道理的... – Kawu 2010-10-31 12:02:15

+0

@Kawu:也許我沒有聽到你說的話,但當你重複上面的映射時,你必須使用JoinColumn中的可插入/可更新來使關聯成爲只讀。如果它不起作用,則顯示允許重現的映射和一些說明問題的痕跡。 – 2010-10-31 13:24:03

+0

讓我澄清一下:JPA 1.0不允許在關聯上使用@Id,這就是爲什麼在Project中有兩個冗餘成員deptNumber和deptCountry。由於這兩個是Departments表中的PK,因此項目的組合鍵類ProjectId具有DeptId類型的成員。但Hibernate和EclipseLink都會拋出映射異常,因爲它們不能將兩個冗餘的@Id成員deptNumber和deptCountry映射到DeptId的屬性。我想知道這是一個普遍的限制,還是有辦法告訴JPA 1.0 ORM如何映射它們。 (JPA 1.0要求字段的名稱匹配) – Kawu 2010-11-01 11:03:06

3

是的,這是JPA 1.0的限制,在JPA 2.0中進行了更正。在新的JPA 2.0中,您可以將ID註釋放在您的部門關係上,並完全避免使用重疊的deptCountry和deptNumber屬性,並且鍵類使用嵌套。在JPA 1.0中,只有基本映射可以標記爲ID的一部分,需要重新映射映射和一些代碼以確保值/關係在持久存儲時正確放入緩存。由於冗餘,正如其他答案中所述,字段映射之一需要通過insertable/updatable = false標記爲只讀。這樣做雖然意味着值不會合併到緩存中 - 所以更改(例如插入時,因爲一旦存在就不能更改對象ID)將不會被反映,除非對象從數據庫刷新。如果您將JoinColumns標記爲只讀,則需要從引用的部門獲取值,並在您想要保留項目時手動將它們放入相應的基本ID屬性中。但是,您也可以將基本屬性標記爲只讀。 Eclipselink無論如何不會有任何問題,並將使用關聯的部門實體正確設置字段值(只要它在項目上調用persist之前設置)。不過請注意,當您在不同的上下文中回讀項目時,可能會或可能不會填充基本屬性 - 這取決於實體是否從數據庫中刷新。如果它們是隻讀的,則它們不會合併到共享緩存中,因爲它們只能讀取,不應該更改。因此,他們可以被忽略,或者如果他們必須填充,實體刷新或在事件中從部門設置的值。

通過使用JPA2.0 @MapsId,可以重複使用相同的模型,該模型還將使用來自關係的值爲您保留基本映射。只有我看到的是,你不需要訪問關係(可能導致不必要的連接或懶惰關係上的數據庫訪問)來獲取外鍵/ ID字段值。

至於ZipArea EclipseLink異常,它們是由於ZipAreaId具有ZipId zip屬性而不是它被展平。 JPA 1.0要求密鑰類具有與實體中每個@ID屬性相同類型和名稱的屬性。