2017-05-23 3 views
0

Ich habe zwei TabellenHibernate OneToMany-Konfiguration. Hilfe benötigt

Table Student Columns (Rollnumber, ....) 
Table Phone Columns (STUD_ID,ID, phonetype, number) 

Student-Klasse ist

@Entity 
@Table 
public class Student { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    int rollNumber; 

    @OneToMany 
    Set<Phone> contacts; 
    : 
    : // Getter setters 
} 

Telefon Klasse ist

@Entity 
public class Phone { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    int id; 
    @Column 
    String type; 
    @Column 
    String number; 
: 
: // Getter setters 

}

Aber das funktioniert nicht

 Student s1 = session.get(Student.class, 24); 

     Phone p1 = new Phone(); 
     p1.setNumber("1111111"); 
     p1.setType("Ghar"); 


     Phone p2 = new Phone(); 
     p2.setNumber("222222"); 
     p2.setType("Office"); 


     Set<Phone> phoneSet = new HashSet<>(); 
     phoneSet.add(p1); 
     phoneSet.add(p2); 

     s1.setContacts(phoneSet); 

     session.save(s1); 

Aber dies erstellt keinen Datensatz in "Telefon" -Tabelle. In Phone-Klasse brauche ich kein Student-Objekt. Welche zusätzliche Konfiguration benötigt.

Teillösung

Schließlich war ich in der Lage, es zu tun. Mit "Cascade" und "Joincolumn" wie folgt.

@OneToMany(cascade=CascadeType.ALL) 
@JoinColumn(name="STUD_ID") 
public Set<Phone> getContacts() { 
    return contacts; 
} 

Abfragen werden gebrannt, wie (wie erwartet) über

Hibernate: select student0_.rollNumber as rollNumb1_3_0_, student0_.ADDR_ID as ADDR_ID4_3_0_, student0_.CLASS_TEACHER_ID as CLASS_TE5_3_0_, student0_.name as name2_3_0_, student0_.surname as surname3_3_0_, address1_.ID as ID1_0_1_, address1_.Country as Country2_0_1_, address1_.details as details3_0_1_, teacher2_.teacherId as teacherI1_4_2_, teacher2_.name as name2_4_2_, teacher2_.surname as surname3_4_2_ from Student student0_ left outer join ADDRESS address1_ on student0_.ADDR_ID=address1_.ID left outer join Teacher teacher2_ on student0_.CLASS_TEACHER_ID=teacher2_.teacherId where student0_.rollNumber=? 
Hibernate: call next value for hibernate_sequence 
Hibernate: call next value for hibernate_sequence 
Hibernate: insert into Phone (number, stud_id, type, id) values (?, ?, ?, ?) 
Hibernate: insert into Phone (number, stud_id, type, id) values (?, ?, ?, ?) 
Hibernate: update Phone set STUD_ID=null where STUD_ID=? 
Hibernate: update Phone set STUD_ID=? where id=? 
Hibernate: update Phone set STUD_ID=? where id=? 

Aber wie gesehen folgt feuert Abfrage "gesetzt Update Phone STUD_ID = null, wo STUD_ID =?". Was soll ich tun, damit es ausgelöst wird? Mit

@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true) 

Wurf Ausnahmen

Caused by: org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.kaushik.winnersoft.data.Student.contacts 

Lösung

@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true) 
@JoinColumn(name="STUD_ID") 
public Set<Phone> getContacts() { 
    return contacts; 
} 

Wie akzeptierte Lösung erwähnt verändert den Code.

s1.getContacts().clear(); 
Phone p1 = new Phone(); 
s1.getContacts().add(p1); 
Phone p2 = new Phone(); 
s1.getContacts().add(p2); 

Löschen Abfragen wurden auch ausgelöst. Alle Anfragen waren

Hibernate: select student0_.rollNumber as rollNumb1_3_0_, student0_.ADDR_ID as ADDR_ID4_3_0_, student0_.CLASS_TEACHER_ID as CLASS_TE5_3_0_, student0_.name as name2_3_0_, student0_.surname as surname3_3_0_, address1_.ID as ID1_0_1_, address1_.Country as Country2_0_1_, address1_.details as details3_0_1_, teacher2_.teacherId as teacherI1_4_2_, teacher2_.name as name2_4_2_, teacher2_.surname as surname3_4_2_ from Student student0_ left outer join ADDRESS address1_ on student0_.ADDR_ID=address1_.ID left outer join Teacher teacher2_ on student0_.CLASS_TEACHER_ID=teacher2_.teacherId where student0_.rollNumber=? 
Hibernate: select contacts0_.STUD_ID as STUD_ID3_2_0_, contacts0_.id as id1_2_0_, contacts0_.id as id1_2_1_, contacts0_.number as number2_2_1_, contacts0_.stud_id as stud_id3_2_1_, contacts0_.type as type4_2_1_ from Phone contacts0_ where contacts0_.STUD_ID=? 
Hibernate: call next value for hibernate_sequence 
Hibernate: call next value for hibernate_sequence 
Hibernate: insert into Phone (number, stud_id, type, id) values (?, ?, ?, ?) 
Hibernate: insert into Phone (number, stud_id, type, id) values (?, ?, ?, ?) 
Hibernate: update Phone set STUD_ID=null where STUD_ID=? and id=? 
Hibernate: update Phone set STUD_ID=null where STUD_ID=? and id=? 
Hibernate: update Phone set STUD_ID=? where id=? 
Hibernate: update Phone set STUD_ID=? where id=? 
Hibernate: delete from Phone where id=? 
Hibernate: delete from Phone where id=? 

Antwort

1

Der Grund des Fehlers

A collection with cascade="all-delete-orphan" was no longer referenced ... 

ist, dass Hibernate eine Sammlung mit orphanRemoval=true über einen Proxy-Tracks.

So haben Sie wirklich einen Proxy in Ihrer persistenten Klasse (wenn Sie eine Student aus einer Datenbank mit session.get(Student.class, 24) erhalten):

@Entity 
@Table 
public class Student { 

    @OneToMany 
    HibernateProxySet<Phone> contacts; 

} 

Wenn Sie diese

s1.setContacts(phoneSet); 

Sie, natürlich, Überschreibung HibernateProxySet von Ihrem HashSet. Hibernate generiert HibernateException in dieser Situation, da es alle Änderungen an dem contacts mithilfe HibernateProxySet verfolgen möchte.

Wie

@Entity 
@Table 
public class Student { 

    @OneToMany 
    Set<Phone> contacts = new HashSet<>(); 

} 

s1.getContacts().clear(); 
s1.getContacts().add(p1); 
s1.getContacts().add(p2); 

ich eine contacts Feldinitialisierung haben zu lösen, indem new HashSet<>() hinzugefügt. Es ist natürlich nicht zwingend notwendig. Sie können über die Verwendung einer solchen Strategie in jeder persistenten Klasse nachdenken.

Sie können auch eine zusätzliche Methode zu Student hinzufügen, um Kontakte hinzuzufügen. Weitere Informationen finden Sie hier:

Hibernate - A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance