2015-11-09 82 views
0

我試圖在兩個實體之間創建一個雙向一對多關聯,其中多邊有一個複合關鍵字。而許多方面的關鍵之一就是來自一方。另外,我需要協會的擁有者多方。以下是顯示我的代碼外觀的示例代碼。休眠雙向一對多複合密鑰

沒有Jointable

父類是一側。我需要這個協會的這邊老闆。

public class parent{ 

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

    @OneToMany(fetch=FetchType.LAZY) 
    @JoinColumns({ 
        @JoinColumn(name="NAME", nullable = false), 
        @JoinColumn(name="PARENT", nullable = false)}) 
    private Set<Child> childs; 
} 

子類是多方面。它的主鍵是「名字」和「父母」。 「父母」來自協會。

public class child{ 

    @EmbeddedId 
    @AttributeOverrides({ 
      @AttributeOverride(name="parent", [email protected](name="PARENT", nullable=false)), 
      @AttributeOverride(name="name", [email protected](name="NAME", nullable=false))}) 
    private ChildId id; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumns({ 
        @JoinColumn(name="PARENT", nullable = false, updatable = false, insertable = false), 
        @JoinColumn(name="NAME", nullable = false, updatable = false, insertable = false)}) 
    private Parent parent; 
} 

ChildId是Embedded id。

@Embeddable 
public class childId{ 

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

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

隨着Jointable

父類

public class parent{ 

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

    @OneToMany(fetch = FetchType.LAZY) 
    @JoinTable(name="PARENTCHILD", 
       joinColumns= {@JoinColumn(name="PNAME", referencedColumnName = "NAME", nullable = false)}, 
       inverseJoinColumns = { 
         @JoinColumn(name="CNAME", referencedColumnName = "NAME", nullable = false), 
         @JoinColumn(name="CPNAME", referencedColumnName = "PARENT", nullable = false)}) 
    private Set<Child> childs; 
} 

子類

public class child{ 

    @EmbeddedId 
    @AttributeOverrides({ 
      @AttributeOverride(name="parent", [email protected](name="PARENT", nullable=false)), 
      @AttributeOverride(name="name", [email protected](name="NAME", nullable=false))}) 
    private ChildId id; 

    @MapsId("parent") 
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinTable(name="PARENTCHILD", 
       inverseJoinColumns = {@JoinColumn(name="PNAME", referencedColumnName = "NAME", nullable = false)}, 
       joinColumns = { 
         @JoinColumn(name="CNAME", referencedColumnName = "NAME", nullable = false), 
         @JoinColumn(name="CPNAME", referencedColumnName = "PARENT", nullable = false)}) 
    private Parent parent; 
} 

問題1: 此代碼不能正常工作。如果「沒有連接」,它會給出以下例外。

Caused by: org.hibernate.AnnotationException: A Foreign key refering com.entity.Parent from com.entity.Child has the wrong number of column. should be 1 

問題2: 而在「與jointable」的情況下,它提供例外如下:

SQLCODE=-530, SQLSTATE=-23503, SQLERRMC=PARENTCHILD.FK_PARENTCHILD_CHILD 
+0

你不需要有這個問題的複合鍵,作爲父母的名字將被Hibernate itself.To插入的外鍵兒童讓Parent作爲關係的所有者,請在child @ManyToOne中添加mappedBy = parent。這應該可以解決你所有的問題。 請驗證並接受我用下面的代碼片段給出的答案。 –

+0

我給你的答案中的代碼,你不需要加入,只是嘗試我給的代碼。請參閱下面的答案,嘗試該代碼,讓我知道你面對什麼問題。 –

+0

謝謝@BirajChoudhury。我知道這很多,父母將作爲外鍵在子表中。但是,假設孩子的獨特性與父母的名字一致。然後,假設孩子的主鍵爲EmbeddedId,你的代碼將和我的一樣。 – amir

回答

1

你不需要單獨的兒童保持父名稱爲ID,Hibernate會爲你做的。我做了一個更簡單的設計。您可以通過使用mappedBy = childs來控制關係,在@ManyToOnemappedBy = parent@ManyToOne一側。

@Entity 
    public class Parent{ 

    @Id 
    private String name; 

    @OneToMany(fetch= FetchType.LAZY) 
    private Set<Child> childs; 

    public Parent(String name) { 
     this.name = name; 
    } 
    public Parent(){} 
} 

@Entity 
public class Child{ 

    @Id 
    private String name; 

    @ManyToOne(fetch=FetchType.LAZY) 
    private Parent parent; 
} 

三個表會由Hibernate

生成

子表的列名(主鍵),PARENT_NAME(外鍵) 父表中有一列名(主鍵) Parent_child表有兩列parent_name和child_name

編輯:解決方案根據amir的需要改變,只需添加mappedBy無論你需要哪一方來控制關係。

@Entity 
public class Child implements Serializable { 

    @Id 
    private String name; 

    @Id 
    @ManyToOne(fetch=FetchType.LAZY) 
    private Parent parent; 
} 

@Entity 
public class Parent{ 

    @Id 
    private String name; 

    @OneToMany(fetch= FetchType.LAZY) 
    private Set<Child> childs; 

    public Parent(String name) { 
     this.name = name; 
    } 
    public Parent(){} 
} 

編輯 - 在孩子邊名稱列

@Id() 
@ManyToOne(fetch=FetchType.LAZY) 
@JoinColumn(name="xyz") 
private Parent parent; 
+0

男人,仍然是你給的Child類的主鍵只有** Name **屬性。子的主鍵由兩個屬性組成: 1-名稱 2-父母(此名稱也是「名稱」名稱下的父類的主鍵) 只需查看我的代碼 – amir

+0

執行它並查看I我能夠看到3個表,Table子現在有2個主鍵,而parent_child表現在有3列,父,子和child_parent。我正在爲你執行代碼,並且你抱怨沒有執行這是不公平的。 –

+0

如果有效,請接受答案。 –

0

要使用連接表,使用下面的代碼使用一個一對多的雙向映射:

父類

public class parent{ 
     @Id 
     @Column(name = "id") 
     @GeneratedValue(strategy = GenerationType.IDENTITY)  
     private Long id; 
     ..... 
     ..... 
     @OneToMany(cascade=CascadeType.ALL) 
     @JoinTable(name="Parent_Child", joinColumns={@JoinColumn(name ="parentId", referencedColumnName ="id")}, 
      inverseJoinColumns={@JoinColumn(name ="childId", referencedColumnName ="id")}) 
     private Set<Child> children; 
     ..... 
     ..... 
} 

子類

public class Child{ 
     @Id 
     @Column(name = "id") 
     @GeneratedValue(strategy = GenerationType.IDENTITY)  
     private Long id; 
     ..... 
     ..... 
     @OneToOne(cascade=CascadeType.ALL) 
     @JoinTable(name="Parent_Child", joinColumns={@JoinColumn(name ="childId", referencedColumnName ="id")}, 
      inverseJoinColumns={@JoinColumn(name ="parentId", referencedColumnName ="id")}) 
     private Parent parent; 
     ..... 
     ..... 
} 

請注意,我用OneTOMany映射Parent類 - 原因按你的邏輯,家長可以有多個孩子,我已經使用OneToOne映射Child類原因一個孩子將有一位家長(如您的要求中所述)。

希望這有助於

+0

您不應該使用CascadeType.ALL在關係的兩端,就像刪除一個Child一樣,它會嘗試刪除它的父節點,但它不能刪除父節點,因爲該父節點的所有其他子節點仍然是活動的,所以Hibernate會拋出錯誤。同樣刪除父母會殺死所有的孩子。請理解這是一種關係而不是構圖。 –

+0

另外,您添加的大部分註釋都不是必需的,表格ID已經是自解釋性的,因爲它是名稱。你需要添加@Column(name =「xyz」)來增加含義並提高可讀性,但是在這裏你正在改變一個完全可讀的表來隱藏命名。這不會增加任何值,但會減少值。也不需要@JoinTable。當Hibernate爲你做所有工作時,爲什麼你會膨脹代碼。 –