2012-09-23 19 views
7

Ciao sto leggendo la documentazione di ibernazione.Ignorato da molti a molti lato inverso ignorato

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html

A molti-a-molti è definito logicamente usando l'annotazione @ManyToMany . Devi anche descrivere la tabella di associazione e le condizioni di join usando l'annotazione @JoinTable. Se l'associazione è bidirezionale, un lato deve essere il proprietario e un lato deve essere fine inversa (cioè viene ignorato durante l'aggiornamento del rapporto valori nella tabella di associazione.):

I capire tutto tranne l'ultimo

(ad esempio, verrà ignorato quando si aggiornano i valori di relazione nella tabella di associazione).

Cosa significa? Esempio?

risposta

22

Supponiamo di avere le seguenti entità:

lato
@Entity 
public class Student { 
    @ManyToMany 
    private Set<Course> courses; 
    ... 
} 

@Entity 
public class Course { 
    @ManyToMany(mappedBy = "courses") 
    private Set<Student> students; 
    ... 
} 

Il proprietario è Student (perché non ha l'attributo mappedBy). Il lato inverso è da golf ((perché ha l'attributo mappedBy)

Se fate la seguente:.

Course course = session.get(Course.class, 3L); 
Student student = session.get(Student.class, 4L); 
student.getCourses().add(course); 

Hibernate aggiungerà una voce per studente 4 e naturalmente 3 nella tabella unirsi perché aggiornati il lato titolare dell'associazione (student.courses)

Mentre se si eseguono le seguenti:.

Course course = session.get(Course.class, 3L); 
Student student = session.get(Student.class, 4L); 
course.getStudents().add(student); 

non succederà nulla, essere perché hai aggiornato il lato inverso dell'associazione (course.students), ma trascurato di aggiornare il lato proprietario. Hibernate considera solo il lato proprietario.

+0

Grazie! Ottima spiegazione Quindi l'unico modo è aggiornare il proprietario? Entrambi i lati non possono essere proprietari? Come se mi piacerebbe che funzionasse in entrambi i modi? Non possibile? – pethel

+0

Sì, è necessario aggiornare il lato proprietario. Solo un lato può essere il proprietario. Non c'è modo di farlo funzionare in entrambi i modi. –

+0

@JBNizet e cosa dici della risposta qui sotto? – azerafati

2

Per farlo funzionare in entrambi i modi è necessario disporre di due relazioni separate tra le entità. Questo può essere rappresentato da una tabella di join nel database ma per impostazione predefinita sarà rappresentato da due, quindi devi dire esplicitamente che vuoi una tabella di join.

Lo dimostrerò utilizzando il modello di Studente e Corso precedentemente menzionato.

@Entity 
public class Student { 
    @ManyToMany 
    @JoinTable(name = "student_course", 
       joinColumns = {@JoinColumn(name = "courses_id")}, 
       inverseJoinColumns = {@JoinColumn(name = "students_id")}) 
    private Set<Course> courses; 
    ... 
} 

@Entity 
public class Course { 
    @ManyToMany 
    @JoinTable(name = "student_course", 
       joinColumns = {@JoinColumn(name = "students_id")}, 
       inverseJoinColumns = {@JoinColumn(name = "courses_id")}) 
    private Set<Student> students; 
    ... 
} 

Nell'esempio precedente abbiamo 2 rapporti con ogni lato della Student < -> rapporto Corso di essere proprietario di una relazione. Quindi questo risolve il problema di salvare le modifiche al database solo dal lato del proprietario poiché ogni lato è proprietario di una relazione.

Ma dobbiamo tenere a mente un fatto che, dopo il salvataggio dei dati, le collezioni di rapporto NON saranno ricaricati dal database così programmatore necessità di gestire collezioni di relazione da lui stesso.Dicendo questo voglio dire che il modo più semplice è quello di modificare setter per le collezioni di relazione per ricostruire il ciclo tra entità come questo:

public void setCourses(Set<Course> courses) { 
    for(Course c : courses) { 
     if (!c.getStudents().contains(this)) { 
      c.getStudents().add(this); 
     } 
    } 
    this.courses = courses; 
} 

public void setStudents(Set<Student> students) { 
    for(Student s : students) { 
     if (!s.getCourses().contains(this)){ 
      s.getCourses().add(this); 
     } 
    } 
    this.students = students; 
}