2012-06-15 53 views
2

如何使用JPA實現以下關係?如何建立多對多關係

table person (
    id int, 
    name text 
) 

table person_home (
    person_id int, 
    home_id int, 
    type char(1)  -- 'p' = primary, 's' = secondary 
) 

table home (
    id int, 
    address text 
) 

一個人可以有許多家庭,和家庭可以有多少人生活在它(即多對多的關係)。 此外,一個家庭可以成爲一個人的主要居所,但同時又是另一個人的二級居所。

即使數據庫模式已清除,我也不確定如何建模此關係。

我想過將映射表person_home拆分成person_primary_home和person_secondary_home,但是如果可能的話,我寧願保留模式。

回答

1

這個問題是相當多問,在這裏回答:
How to create a composite primary key which contains a @ManyToOne attribute as an @EmbeddedId in JPA?

您需要四類:

  1. Person.java
  2. Home.java
  3. PersonH​​ome.java
  4. PersonH​​omePk.java

您創建的Person.java和Home.java文件與PersonH​​ome.java具有一對多關係。他們將有@Id字段來識別主鍵。每個將有一個@OneToMany關係,至少映射到其在PersonH​​ome實體中的各自字段的mappedBy屬性。即在Person.java你可以有,而不是一個@Id柱像

@OneToMany(cascade = CascadeType.ALL, mappedBy = "Person") 
private Collection<PersonHome> personHome; 

的PersonH​​ome.java將有一個@EmbeddedId字段來標識PersonH​​omePk實例聲明這是其主鍵(也就是你將有@EmbeddedId註釋表示連接表PersonH​​ome的主鍵的類的聲明)。任何其他字段都被聲明爲普通列。 PersonH​​ome.java還將聲明兩個ManyToOne關係,分別對應於人和家庭。這些將使用@JoinColumn註釋(確保它們具有可插入屬性= false和可更新= false)。數據類型將是Person和Home類。即

@EmbeddedId 
protected PersonHomePk personHomePk; 
@Column (name = "type") 
private String type; 
@JoinColumn(name = "person_id", referencedColumnName = "person_id", insertable = false, updatable = false) 
@ManyToOne(optional = false) 
private Person person; 

你也需要同樣的「Home」聲明。

你爲什麼只用一個字符作爲「類型」。我建議使用varchar,這樣一旦你離開後維護這個東西的人會在你不在的時候更好地理解代碼和數據庫。 '分離'更容易理解'd'。

0

我相信,如果除了person_home表格上的關係之外,您還需要使用三個具有兩個一對多關係的對象,以便能夠訪問所有數據。

通過擁有primary_home_id和secondary_home_id,您可以通過從人員表格到主表格建立兩個多對一的關係來消除這種需求 - 除非我在這裏缺少一個需求,並且一個人可以有多個小學或中學家庭。

+0

是的,一個人可以有不止一種類型的房屋。所以答案是我需要將映射表建模爲一個類? –

+0

如果你想以某種方式獲得'type'列,那麼我相信是的。 – ametren

+0

我遇到了這個問題,因爲這對於關係有元數據非常有用。我相信我找到了一種將其稱爲「多對多」的方法,但我必須讓對象代表這種關係。把它想象成兩個「一對多」關係更容易。 – ametren