31

Eine andere Hibernate Frage ...: PHibernate many-to-many-Vereinigung mit der gleichen Einheit

Mit Hibernate Annotations Framework, ich habe eine User Einheit. Jede User kann eine Sammlung von Freunden haben: eine Sammlung von anderen User s. Ich konnte jedoch nicht herausfinden, wie eine Many-to-Many-Assoziation innerhalb der User-Klasse erstellt wird, die aus einer Liste von User s besteht (mithilfe einer Benutzerfreunde-Zwischentabelle).

Hier ist die Benutzerklasse und ihre Anmerkungen:

@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; 
} 

Der Benutzer-Freund Zuordnungstabelle hat nur zwei Spalten, von denen beide Fremdschlüssel auf die uid Spalte der tbl_users Tabelle sind. Die zwei Spalten sind personId (die dem aktuellen Benutzer zugeordnet werden sollte) und friendId (die die ID des Freundes des aktuellen Benutzers angibt).

Das Problem ist, das "Freunde" -Feld bleibt Null, obwohl ich die Freundes-Tabelle so ausgefüllt habe, dass alle Benutzer im System mit allen anderen Benutzern befreundet sind. Ich habe sogar versucht, die Beziehung auf @OneToMany zu wechseln, und es kommt immer noch Null (obwohl die Hibernate-Debug-Ausgabe zeigt eine SELECT * FROM tbl_friends WHERE personId = ? AND friendId = ? Abfrage, aber sonst nichts).

Haben Sie Ideen, wie Sie diese Liste auffüllen können? Vielen Dank!

Antwort

47

@ManyToMany zu Selbst ist eher verwirrend, weil die Art, wie Sie normalerweise modellieren würden, sich vom "Hibernate" Weg unterscheidet. Ihr Problem ist, dass Sie eine andere Sammlung vermissen.

Denken Sie es so an - wenn Sie "Autor"/"Buch" als "Viele-zu-Viele" zuordnen, benötigen Sie "Autoren" Sammlung auf Buch und "Bücher" Sammlung auf Autor. In diesem Fall repräsentiert Ihre Entität "Benutzer" beide Enden einer Beziehung. Sie müssen „meine Freunde“ und „Freund“ Sammlungen:

@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; 

Sie können immer noch die gleiche Zuordnungstabelle verwenden, aber beachten Sie, dass Leveln/inverseJon Spalten werden auf Sammlungen getauscht.

Die Sammlungen "friends" und "friendOf" können übereinstimmen oder auch nicht (abhängig davon, ob Ihre "Freundschaft" immer gegenseitig ist) und Sie müssen diese natürlich nicht in Ihrer API offen legen, aber das ist es wie man es in Hibernate abbildet.

+0

ich Sie hoffen, Ich bin zum dritten Mal zu meiner Rettung gekommen :) Es hat perfekt funktioniert, und deine Erklärung hat mein Verständnis von ER deutlich verbessert. Vielen Dank noch einmal! :) – Magsol

+1

Darf ich Freunde und Freunde kombinieren? Und wenn nicht, dann brauche ich Hilfe mit jsonmanagedreference und jsonbackreference in einer Entität in dieser Frage: http://stackoverflow.com/questions/24563066/hibernate-user-and-friends-jsonreference – dikkini

+0

Ich benutze Hibernate 5 und eine Sammlung ist genug - die Verwendung von zwei erstellt doppelte Zeilen in tbl_friends. – mdziob

0

Eigentlich seine sehr einfach und könnte durch folgende sagen Sie haben folgende Unternehmen

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 für gleiche erreicht werden:

<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> 

Und Testfall

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(); 
    } 

}