1. Introducción
En este tutorial rápido, veremos rápidamente cómo se puede usar la anotación @ManyToMany para especificar este tipo de relaciones en Hibernate.
2. Un ejemplo típico
Comencemos con un diagrama de relación de entidades simple, que muestra la asociación de muchos a muchos entre dos entidades empleado y proyecto:

En este escenario, cualquier empleado puede asignarse a varios proyectos y un proyecto puede tener varios empleados trabajando para él, lo que lleva a una asociación de varios a varios entre los dos.
Tenemos un empleado de mesa con employee_id como su clave principal y un proyecto de mesa con project_id como su clave primaria. Aquí se requiere una tabla de unión employee_project para conectar ambos lados.
3. Configuración de la base de datos
Supongamos que tenemos una base de datos ya creada con el nombre spring_hibernate_many_to_many.
También tenemos que crear los empleados y de proyectos tablas junto con el employee_project tabla de unión con employee_id y project_id como claves externas:
CREATE TABLE `employee` ( `employee_id` int(11) NOT NULL AUTO_INCREMENT, `first_name` varchar(50) DEFAULT NULL, `last_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`employee_id`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8; CREATE TABLE `project` ( `project_id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(50) DEFAULT NULL, PRIMARY KEY (`project_id`) ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; CREATE TABLE `employee_project` ( `employee_id` int(11) NOT NULL, `project_id` int(11) NOT NULL, PRIMARY KEY (`employee_id`,`project_id`), KEY `project_id` (`project_id`), CONSTRAINT `employee_project_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `employee` (`employee_id`), CONSTRAINT `employee_project_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `project` (`project_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Con la base de datos configurada, el siguiente paso sería la preparación de las dependencias de Maven y la configuración de Hibernate. Para obtener información sobre esto, consulte el artículo sobre la Guía de Hibernate4 con Spring
4. Las clases modelo
Las clases modelo Empleado y Proyecto deben crearse con anotaciones JPA:
@Entity @Table(name = "Employee") public class Employee { // ... @ManyToMany(cascade = { CascadeType.ALL }) @JoinTable( name = "Employee_Project", joinColumns = { @JoinColumn(name = "employee_id") }, inverseJoinColumns = { @JoinColumn(name = "project_id") } ) Set projects = new HashSet(); // standard constructor/getters/setters }
@Entity @Table(name = "Project") public class Project { // ... @ManyToMany(mappedBy = "projects") private Set employees = new HashSet(); // standard constructors/getters/setters }
Como podemos ver, tanto la clase Empleado como las clases Proyecto se refieren entre sí, lo que significa que la asociación entre ellas es bidireccional.
Para mapear una asociación de muchos a muchos, usamos las anotaciones @ManyToMany , @JoinTable y @JoinColumn . Echemos un vistazo más de cerca.
La anotación @ManyToMany se usa en ambas clases para crear la relación de muchos a muchos entre las entidades.
Esta asociación tiene dos lados, es decir, el lado propietario y el lado inverso. En nuestro ejemplo, el lado propietario es Empleado, por lo que la tabla de combinación se especifica en el lado propietario utilizando la anotación @JoinTable en la clase Empleado . El @JoinTable se utiliza para definir la tabla de unión / enlace. En este caso, es Employee_Project.
La anotación @JoinColumn se utiliza para especificar la columna de unión / enlace con la tabla principal. Aquí, la columna de combinación es employee_id y project_id es la columna de combinación inversa, ya que Project está en el lado inverso de la relación.
En la clase Project , el atributo mappedBy se usa en la anotación @ManyToMany para indicar que la colección de empleados está asignada por la colección de proyectos del lado del propietario.
5. Ejecución
Para ver la anotación de muchos a muchos en acción, podemos escribir la siguiente prueba JUnit:
public class HibernateManyToManyAnnotationMainIntegrationTest { private static SessionFactory sessionFactory; private Session session; // ... @Test public void givenData_whenInsert_thenCreatesMtoMrelationship() { String[] employeeData = { "Peter Oven", "Allan Norman" }; String[] projectData = { "IT Project", "Networking Project" }; Set projects = new HashSet(); for (String proj : projectData) { projects.add(new Project(proj)); } for (String emp : employeeData) { Employee employee = new Employee(emp.split(" ")[0], emp.split(" ")[1]); assertEquals(0, employee.getProjects().size()); employee.setProjects(projects); session.persist(employee); assertNotNull(employee); } } @Test public void givenSession_whenRead_thenReturnsMtoMdata() { @SuppressWarnings("unchecked") List employeeList = session.createQuery("FROM Employee") .list(); assertNotNull(employeeList); for(Employee employee : employeeList) { assertNotNull(employee.getProjects()); } } // ... }
Podemos ver la relación de muchos a muchos entre las dos entidades creadas en la base de datos: las tablas employee , project y employee_project con datos de muestra que representan la relación.
6. Conclusión
En este tutorial, vimos cómo crear asignaciones utilizando las anotaciones de muchos a muchos de Hibernate, que es una contraparte más conveniente en comparación con la creación de archivos de asignación XML.
El código fuente de este tutorial se puede encontrar en GitHub.