2012-09-23 16 views
7

Hola, estoy leyendo la documentación de hibernación.Muchos a muchos hibernan lado inverso ignorado

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

Una asociación muchos-a-muchos se define lógicamente utilizando la anotación @ManyToMany . También debe describir la tabla de asociación y las condiciones de combinación utilizando la anotación @JoinTable. Si la asociación es bidireccional, un lado tiene que ser el propietario y un lado tiene que ser el final inversa (es decir, será ignorado cuando se actualiza la relación valores en la tabla de asociación.):

I entender todo menos el último

(es decir, se ignorará al actualizar los valores de relación en la tabla de asociación).

¿Qué significa esto? ¿Ejemplo?

Respuesta

22

Suponga que tiene las siguientes entidades:

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

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

El propietario es estudiante (ya que no tiene el atributo mappedBy). El lado inverso es golf ((porque tiene el atributo mappedBy)

Si hace lo siguiente:.

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

Hibernate añadir una entrada para estudiantes 4 y por supuesto las 3 de la tabla de unión debido informado el lado propietario de la asociación (student.courses)

Mientras que si hace lo siguiente:.

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

no pasará nada, será porque usted actualizó el lado inverso de la asociación (course.students), pero descuidó actualizar el lado del propietario. Hibernate solo considera el lado del propietario.

+0

Gracias! Muy buena explicación. Entonces, ¿la única forma es actualizar al propietario? Ambas partes no pueden ser dueños ¿verdad? ¿Cómo me gustaría que funcione en ambos sentidos? ¿Imposible? – pethel

+0

Sí, debe actualizar el lado del propietario. Solo un lado puede ser el dueño. No hay forma de hacerlo funcionar en ambos sentidos. –

+0

@JBNizet, y ¿qué dices sobre la respuesta a continuación? – azerafati

2

Para que funcione en ambos sentidos, necesita tener dos relaciones separadas entre sus entidades. Esto se puede representar mediante una tabla de unión en la base de datos pero, de forma predeterminada, estará representada por dos, por lo que debe decir explícitamente que desea una tabla de unión.

Lo demostraré utilizando el modelo de Estudiante y Curso mencionado anteriormente.

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

En el ejemplo anterior tenemos 2 relaciones con cada lado del Estudiante < -> relación Curso de ser dueño de una relación. Esto resuelve el problema de guardar los cambios en la base de datos solo en el lado del propietario, ya que cada lado es dueño de una relación.

Pero tenemos que tener en cuenta que después de guardar los datos, las colecciones de relaciones NO se volverán a cargar desde la base de datos , por lo que el programador debe manejar las colecciones de relaciones por sí mismo.Al decir esto quiero decir que la forma más fácil es modificar los emisores para las colecciones de relación para reconstruir ciclo entre las entidades de la siguiente manera:

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; 
} 
Cuestiones relacionadas