2012-08-13 121 views
349

是什麼區別:JPA JoinColumn VS的mappedBy

@Entity 
public class Company { 

    @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY) 
    @JoinColumn(name = "companyIdRef", referencedColumnName = "companyId") 
    private List<Branch> branches; 
    ... 
} 

@Entity 
public class Company { 

    @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef") 
    private List<Branch> branches; 
    ... 
} 

回答

147

@JoinColumn可能對關係的雙方使用。這個問題是關於在@OneToMany一側使用@JoinColumn(罕見的情況)。這裏的重點在於物理信息重複(列名)以及未優化的SQL查詢,它將產生一些額外的UPDATE語句

根據documentation

由於一個許多是(幾乎)總是在JPA規範的雙向關係所有者側,一對多關聯是通過@OneToMany註釋(的mappedBy = ...)

@Entity 
public class Troop { 
    @OneToMany(mappedBy="troop") 
    public Set<Soldier> getSoldiers() { 
    ... 
} 

@Entity 
public class Soldier { 
    @ManyToOne 
    @JoinColumn(name="troop_fk") 
    public Troop getTroop() { 
    ... 
} 

部隊通過部隊屬性與士兵有雙向一對多的關係。您不必(不得)在mappedBy方中定義任何物理映射。

要映射雙向一對多,與一個一對多側爲所屬端,你必須刪除的mappedBy元素,並設置多對一@JoinColumn的插入和更新爲false。此解決方案未經優化,將生成一些額外的UPDATE語句。

@Entity 
public class Troop { 
    @OneToMany 
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information 
    public Set<Soldier> getSoldiers() { 
    ... 
} 

@Entity 
public class Soldier { 
    @ManyToOne 
    @JoinColumn(name="troop_fk", insertable=false, updatable=false) 
    public Troop getTroop() { 
    ... 
} 
+1

我無法弄清楚Troop如何成爲你的第二個片段的所有者,Soldier仍然是所有者,因爲它包含了引用Troop的外鍵。 (我正在使用mysql,我檢查了你的方法)。 – Akhilesh 2013-10-30 07:46:03

+0

這是從文檔頁面'原樣'(粗體是我的) – 2013-11-01 17:43:15

+5

在你的例子中,註解'mappedBy =「troop」'是指哪個字段? – Fractaliste 2014-03-25 09:16:16

408

註釋@JoinColumn表明該實體是關係的所有者(即:相應的表有一個帶有被引用表的外鍵的列),而屬性mappedBy指示此端的實體與關係相反,並且所有者駐留在「其他」實體中。這也意味着您可以從您已用「mappedBy」註解的類(完全雙向關係)訪問其他表。

特別是在問題的代碼正確的註釋是這樣的:

@Entity 
public class Company { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "company") 
    private List<Branch> branches; 
} 

@Entity 
public class Branch { 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "companyId") 
    private Company company; 
} 
+3

在這兩種情況下Branch都有公司ID字段。 – 2012-08-13 16:25:27

+2

公司表沒有包含引用表的外鍵的列 - 分支引用了公司..爲什麼你要說「對應的表具有帶引用表的外鍵的列」?你能否再解釋一下。 – 2012-08-13 16:33:14

+7

@MykhayloAdamovych我用示例代碼更新了我的答案。請注意,在'Company' – 2012-08-13 16:33:42

22

註釋的mappedBy理想地應該總是在雙向定向關係的Parent側(公司類)一起使用,在這種情況下,它應該是在公司類指向成員變量「公司」的子類(分類類)

註釋@JoinColumn用於指定加入實體關聯的映射列,此註釋可用於任何類(Parent或Child),但理想情況下應僅用於一方(無論是在父母班還是在孩子班都不在兩方面),在這種情況下,我用它在孩子表示Branch類中的外鍵的雙向關係的邊(分支類)。

下面

是工作示例:

父類,公司

@Entity 
public class Company { 


    private int companyId; 
    private String companyName; 
    private List<Branch> branches; 

    @Id 
    @GeneratedValue 
    @Column(name="COMPANY_ID") 
    public int getCompanyId() { 
     return companyId; 
    } 

    public void setCompanyId(int companyId) { 
     this.companyId = companyId; 
    } 

    @Column(name="COMPANY_NAME") 
    public String getCompanyName() { 
     return companyName; 
    } 

    public void setCompanyName(String companyName) { 
     this.companyName = companyName; 
    } 

    @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="company") 
    public List<Branch> getBranches() { 
     return branches; 
    } 

    public void setBranches(List<Branch> branches) { 
     this.branches = branches; 
    } 


} 

子類,科

@Entity 
public class Branch { 

    private int branchId; 
    private String branchName; 
    private Company company; 

    @Id 
    @GeneratedValue 
    @Column(name="BRANCH_ID") 
    public int getBranchId() { 
     return branchId; 
    } 

    public void setBranchId(int branchId) { 
     this.branchId = branchId; 
    } 

    @Column(name="BRANCH_NAME") 
    public String getBranchName() { 
     return branchName; 
    } 

    public void setBranchName(String branchName) { 
     this.branchName = branchName; 
    } 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="COMPANY_ID") 
    public Company getCompany() { 
     return company; 
    } 

    public void setCompany(Company company) { 
     this.company = company; 
    } 


} 
16

我只是想補充一點@JoinColumn做並不總是必須與物理相關的信息位置 as this答案建議。即使父表沒有指向子表的表數據,也可以將@JoinColumn@OneToMany結合使用。

How to define unidirectional OneToMany relationship in JPA

Unidirectional OneToMany, No Inverse ManyToOne, No Join Table

這似乎只能在JPA 2.x+可用雖然。這對於希望子類僅包含父代的ID而非完整引用的情況很有用。

+0

你是對的,支持單向OneToMany而無連接表在JPA2中引入 – aurelije 2016-12-29 10:38:35