31

另一種休眠的問題休眠許多-to-many關聯...:P與同一實體

使用Hibernate的註解框架,我有一個User實體。每個User可以有一個朋友的集合:其他User s的集合。但是,我無法弄清楚如何在由User s(使用用戶朋友中間表)組成的User類中創建多對多關聯。

這裏的用戶類及其註釋:

@Entity 
@Table(name="tbl_users") 
public class User { 

    @Id 
    @GeneratedValue 
    @Column(name="uid") 
    private Integer uid; 

    ... 

    @ManyToMany(
      cascade={CascadeType.PERSIST, CascadeType.MERGE}, 
      targetEntity=org.beans.User.class 
    ) 
    @JoinTable(
      name="tbl_friends", 
      [email protected](name="personId"), 
      [email protected](name="friendId") 
    ) 
    private List<User> friends; 
} 

的用戶朋友的映射表只有兩列,這兩者都是外鍵的tbl_users表的uid列。這兩列是personId(應映射到當前用戶)和friendId(它指定當前用戶的朋友的ID)。

問題是,即使我已經預先填充好友表,使得系統中的所有用戶都與其他所有用戶成爲好友,但「好友」字段仍然顯示爲空。我甚至嘗試將關係切換爲@OneToMany,它仍然爲null(儘管Hibernate調試輸出顯示SELECT * FROM tbl_friends WHERE personId = ? AND friendId = ?查詢,但沒有其他)。

有關如何填充此列表的任何想法?謝謝!

回答

47

@ManyToMany to self很困惑,因爲你通常建模的方式與「休眠」方式不同。你的問題是你錯過了另一個收藏。

想想這樣 - 如果您將「作者」/「書」映射爲多對多,您需要Book上的「作者」集合和Author上的「books」集合。在這種情況下,您的「用戶」實體代表關係的兩端;所以你需要「我的朋友」和集合「的朋友」:

@ManyToMany 
@JoinTable(name="tbl_friends", 
[email protected](name="personId"), 
[email protected](name="friendId") 
) 
private List<User> friends; 

@ManyToMany 
@JoinTable(name="tbl_friends", 
[email protected](name="friendId"), 
[email protected](name="personId") 
) 
private List<User> friendOf; 

您仍然可以使用相同的關聯表,但需要注意的是加入/ inverseJon列交換的集合。

「friends」和「friendOf」集合可能匹配也可能不匹配(取決於你的「友誼」總是相互的),當然,你不必在你的API中以這種方式公開它們,但這是在Hibernate中映射它的方式。

+0

我希望你'第三次來救我:)它的工作完美無缺,你的解釋清楚了我對ER的理解。非常感謝你,再次! :) – Magsol 2009-11-01 03:53:40

+1

我可以結合朋友和朋友嗎?如果沒有,比我需要在這個問題中的一個實體jsonmanagedreference和jsonbackreference的幫助:http://stackoverflow.com/questions/24563066/hibernate-user-and-friends-jsonreference – dikkini 2014-07-05 07:50:08

+0

我使用Hibernate 5和一個集合就足夠了 - 在tbl_friends中使用兩個創建重複行。 – mdziob 2017-05-26 08:09:41

0

其實它很簡單,可以通過以下說你有以下實體

public class Human { 
    int id; 
    short age; 
    String name; 
    List<Human> relatives; 



    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
    public short getAge() { 
     return age; 
    } 
    public void setAge(short age) { 
     this.age = age; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    public List<Human> getRelatives() { 
     return relatives; 
    } 
    public void setRelatives(List<Human> relatives) { 
     this.relatives = relatives; 
    } 

    public void addRelative(Human relative){ 
     if(relatives == null) 
      relatives = new ArrayList<Human>(); 
     relatives.add(relative); 
    } 




} 

HBM爲同一實現:

<hibernate-mapping> 
    <class name="org.know.july31.hb.Human" table="Human"> 
     <id name="id" type="java.lang.Integer"> 
      <column name="H_ID" /> 
      <generator class="increment" /> 
     </id> 
     <property name="age" type="short"> 
      <column name="age" /> 
     </property> 
     <property name="name" type="string"> 
      <column name="NAME" length="200"/> 
     </property> 
     <list name="relatives" table="relatives" cascade="all"> 
     <key column="H_ID"/> 
     <index column="U_ID"/> 
     <many-to-many class="org.know.july31.hb.Human" column="relation"/> 
     </list> 
    </class> 
</hibernate-mapping> 

和測試用例

import org.junit.Test; 
import org.know.common.HBUtil; 
import org.know.july31.hb.Human; 

public class SimpleTest { 

    @Test 
    public void test() { 
     Human h1 = new Human(); 
     short s = 23; 
     h1.setAge(s); 
     h1.setName("Ratnesh Kumar singh"); 
     Human h2 = new Human(); 
     h2.setAge(s); 
     h2.setName("Praveen Kumar singh"); 
     h1.addRelative(h2); 
     Human h3 = new Human(); 
     h3.setAge(s); 
     h3.setName("Sumit Kumar singh"); 
     h2.addRelative(h3); 
     Human dk = new Human(); 
     dk.setAge(s); 
     dk.setName("D Kumar singh"); 
     h3.addRelative(dk); 
     HBUtil.getSessionFactory().getCurrentSession().beginTransaction(); 
     HBUtil.getSessionFactory().getCurrentSession().save(h1); 
     HBUtil.getSessionFactory().getCurrentSession().getTransaction().commit(); 
     HBUtil.getSessionFactory().getCurrentSession().beginTransaction(); 
     h1 = (Human)HBUtil.getSessionFactory().getCurrentSession().load(Human.class, 1); 
     System.out.println(h1.getRelatives().get(0).getName()); 

     HBUtil.shutdown(); 
    } 

}