Relaciones uno a muchos y muchos a muchos
Mapee @OneToMany, @ManyToMany y @JoinTable con tipos de cascada y estrategias de carga.
Relaciones uno a muchos y muchos a muchos es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
Tipos de relaciones en JPA
JPA admite cuatro tipos de relaciones: @OneToOne, @OneToMany, @ManyToOne, @ManyToMany. Cada uno se asigna a restricciones de clave externa o de tabla de unión.
@ManyToOne: Lado propietario
Una relación de muchos a uno (por ejemplo, muchos pedidos pertenecen a un usuario) se mapea con @ManyToOne y un @JoinColumn para la clave foránea.
@Entity
public class Order {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
}@OneToMany: Lado inverso
El lado inverso (un usuario tiene muchos pedidos) utiliza @OneToMany(mappedBy = "user"). El atributo mappedBy apunta al campo del lado propietario que contiene la FK.
@Entity
public class User {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Order> orders = new ArrayList<>();
}Método auxiliar para la coherencia bidireccional
En las asociaciones bidireccionales, mantenga ambos lados de la relación en un método auxiliar para conservar la coherencia del grafo de objetos antes de hacer flush.
public void addOrder(Order order) {
orders.add(order);
order.setUser(this); // keep both sides in sync
}
public void removeOrder(Order order) {
orders.remove(order);
order.setUser(null);
}Tipos de cascada
CascadeType.ALL propaga todas las operaciones (persistir, fusionar, eliminar, actualizar y desvincular) del padre al hijo. PERSIST y MERGE son opciones seguras habituales. REMOVE elimina los hijos cuando se elimina el padre.
@OneToMany(mappedBy = "user",
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
orphanRemoval = true)
private List<Order> orders;orphanRemoval: Eliminación automática de entidades hijas
orphanRemoval = true elimina una entidad hija cuando se quita de la colección del padre, incluso sin llamar explícitamente a entityManager.remove().
user.getOrders().remove(order); // triggers DELETE for the orphaned order on flush@ManyToMany con @JoinTable
Una relación de muchos a muchos (por ejemplo, entre estudiantes y cursos) utiliza una tabla de unión. Defínala en el lado propietario con @JoinTable; el lado inverso utiliza mappedBy.
@Entity
public class Student {
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private Set<Course> courses = new HashSet<>();
}Columnas adicionales en la tabla de unión
Cuando la tabla de unión necesita columnas adicionales (por ejemplo, la fecha de matriculación), convierta @ManyToMany en dos relaciones @OneToMany / @ManyToOne con una entidad nueva que represente la tabla de unión.
@Entity
public class Enrollment {
@ManyToOne Student student;
@ManyToOne Course course;
private LocalDate enrolledAt;
}FetchType: LAZY frente a EAGER
Carga predeterminada: @ManyToOne y @OneToOne son EAGER (cargan inmediatamente). @OneToMany y @ManyToMany son LAZY (cargan al acceder a ellas). Utilice siempre LAZY para las colecciones a fin de evitar consultas N+1.
// Always override to LAZY:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id")
private Category category;Problema de las consultas N+1
Acceder a una colección lazy dentro de un bucle ejecuta una consulta por entidad (N+1). Soluciónelo con JOIN FETCH en JPQL o con @EntityGraph para cargar la colección en una sola consulta.
// N+1 problem:
List<User> users = repo.findAll();
users.forEach(u -> u.getOrders().size()); // 1 + N queries!
// Fix:
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders")
List<User> findAllWithOrders();Set frente a List para las colecciones
Utilice Set para @ManyToMany (evita filas duplicadas en la tabla de unión). Utilice List para @OneToMany cuando el orden sea importante. No utilice nunca List con @ManyToMany: Hibernate elimina y vuelve a insertar todas las filas.
Comprobación rápida
¿Qué indica mappedBy en una anotación @OneToMany?
Resumen
Utilice @ManyToOne+@JoinColumn en el lado propietario (FK). Utilice @OneToMany(mappedBy=...) en el lado inverso. Use siempre LAZY para las colecciones. Solucione N+1 con JOIN FETCH. Utilice una entidad de unión para las relaciones de muchos a muchos con columnas adicionales.
Preguntas frecuentes
¿La lección «Relaciones uno a muchos y muchos a muchos» es gratis?
Sí — el texto completo de «Relaciones uno a muchos y muchos a muchos» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Relaciones uno a muchos y muchos a muchos»?
Mapee @OneToMany, @ManyToMany y @JoinTable con tipos de cascada y estrategias de carga. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Relaciones uno a muchos y muchos a muchos»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Mapeo de entidades con anotaciones JPA
- Repositorios de Spring Data y métodos de consulta
- Relaciones uno a muchos y muchos a muchos
- Paginación, ordenación y proyecciones