SpringBoot
Tutorial SpringBoot: Asociaciones de entidades JPA
Spring Boot entidades JPA asociaciones: mapeo. Aprende a mapear entidades JPA con asociaciones en Spring Boot con ejemplos prácticos.
Aprende SpringBoot GRATIS y certifícateLas asociaciones de Entidades JPA (Java Persistence API) son una funcionalidad que permite representar relaciones entre distintas tablas en una base de datos en el nivel de las clases de Java.
Esto significa que podemos relacionar clases de Java por medio de Composición y en base de datos se generen claves foráneas apuntando a claves primarias, de modo que las tablas estén relacionadas.
Las asociaciones de Entidades pueden ser de varios tipos, dependiendo de cómo se relacionan las entidades entre sí. Estas pueden ser:
- uno a uno (One-to-One)
- uno a muchos (One-to-Many)
- muchos a uno (Many-to-One)
- muchos a muchos (Many-to-Many)
One-to-One (Uno a Uno)
La relación One-to-One indica que una instancia de una entidad A
sólo puede estar asociada con una única instancia de otra entidad B
, y viceversa.
En otras palabras, hay una correspondencia uno a uno entre las entidades.
Por ejemplo, consideremos una aplicación donde cada User
tiene un único Profile
, y cada Profile
pertenece a un único User
.
En este caso, la relación entre User
y Profile
es One-to-One.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@JoinColumn(name = "profile_id", unique = true)
private Profile profile;
}
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(mappedBy = "profile")
private User user;
}
La anotación @JoinColumn
se utiliza para especificar la columna que será usada para unir la tabla actual con la tabla referenciada. En este caso, se utiliza en la clase Comment
para establecer una relación con Post
:
Por otro lado, mappedBy
se utiliza en el lado "no propietario" (en inglés "non-owning side") de la relación para especificar el campo dentro de la entidad propietaria (en inglés "owning side") que controla la relación:
Aquí, mappedBy = "profile"
indica que la propiedad profile
en la clase User
es el lado "propietario" de la relación. Esto significa que cualquier cambio realizado en el campo profile
de un objeto User
se reflejará en la base de datos. Pero no al revés.
One-to-Many / Many-to-One (Uno a Muchos / Muchos a Uno)
La relación One-to-Many indica que una instancia de una entidad A
puede estar asociada con múltiples instancias de otra entidad B
, pero cada instancia de B
está asociada con un único A
.
Desde la perspectiva de B
a A
, esta relación es Many-to-One.
Por ejemplo, supongamos que en una aplicación de blog, un Post
puede tener múltiples Comment
, pero cada Comment
pertenece a un único Post
. Aquí, la relación entre Post
y Comment
es One-to-Many.
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private List<Comment> comments;
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
}
En una relación bidireccional, como @OneToMany
y @ManyToOne
, se debe designar un lado como el "propietario" de la relación.
El lado propietario es el que controla la actualización de la relación entre las dos entidades. En este caso, Comment
es la entidad propietaria porque contiene el campo @JoinColumn
. Esto significa que si quieres crear, actualizar o eliminar una relación entre un Post
y un Comment
, deberás hacerlo desde el lado de Comment
.
Por ejemplo, si tienes un Post
y quieres añadirle un nuevo Comment
, normalmente lo harías de la siguiente manera:
Post post = new Post();
Comment comment1 = new Comment();
Comment comment2 = new Comment();
comment1.setPost(post);
comment2.setPost(post);
post.setComments(Arrays.asList(comment1, comment2));
Al guardar comment1
y comment2
, la relación se reflejará en la base de datos porque Comment
es el lado propietario de la relación.
Many-to-Many (Muchos a Muchos)
La relación Many-to-Many indica que múltiples instancias de una entidad A
pueden estar asociadas con múltiples instancias de otra entidad B
.
Por ejemplo, en un sistema de gestión de universidades, un Student
puede estar inscrito en múltiples Course
, y un Course
puede tener múltiples Student
inscritos. En este caso, la relación entre Student
y Course
es Many-to-Many.
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToMany
@JoinTable(name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courses;
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToMany(mappedBy = "courses")
private List<Student> students;
}
En cada uno de estos casos, se utilizan anotaciones específicas de JPA para definir la relación y las propiedades correspondientes de las entidades involucradas. En las relaciones Many-to-Many, se utiliza la anotación @JoinTable
para definir la tabla de enlace que maneja la asociación entre las entidades.
En este caso, como la clase Student
es quien tiene la anotación @JoinTable
dentro, será el lado propietario (owner) por lo que para guardar la relación en base de datos será necesario añadir courses al listado de courses de un Student
y persistirlo en base de datos.
Cascada y Fetch
Las operaciones de cascada y las estrategias de carga (fetch) son dos aspectos fundamentales de las relaciones entre entidades en JPA.
Cascada
Las operaciones en cascada son aquellas operaciones que se propagan de una entidad a las entidades relacionadas. Por ejemplo, si se guarda una entidad, y esta tiene una relación en cascada con otras entidades, entonces todas estas entidades se guardarán también.
Las operaciones de cascada disponibles en JPA son:
CascadeType.PERSIST
: Cascada la operaciónpersist
(guardar). Si guardas la entidad fuente, las entidades relacionadas también se guardarán.CascadeType.REMOVE
: Cascada la operaciónremove
(eliminar). Si eliminas la entidad fuente, las entidades relacionadas también se eliminarán.CascadeType.REFRESH
: Cascada la operaciónrefresh
(refrescar). Si refrescas la entidad fuente, las entidades relacionadas también se refrescarán.CascadeType.MERGE
: Cascada la operaciónmerge
(fusionar). Si fusionas la entidad fuente, las entidades relacionadas también se fusionarán.CascadeType.DETACH
: Cascada la operacióndetach
(desconectar). Si desconectas la entidad fuente, las entidades relacionadas también se desconectarán.CascadeType.ALL
: Cascada todas las operaciones anteriores. Si cualquier operación se realiza en la entidad fuente, la misma operación se propagará a las entidades relacionadas.
Aquí hay un ejemplo de cómo se utiliza:
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private List<Comment> comments;
}
En este ejemplo, si un Post
se elimina, todos los Comment
asociados también se eliminarán de la base de datos. Esto es porque la operación remove
se propaga desde Post
a Comment
debido a la configuración CascadeType.ALL
.
Fetch
Fetch se refiere a cuándo se deben cargar los datos de las entidades relacionadas desde la base de datos. JPA ofrece dos estrategias de carga: EAGER y LAZY.
FetchType.EAGER
: Este tipo de carga significa que las entidades relacionadas se cargan al mismo tiempo que la entidad fuente. Por ejemplo, si se carga unPost
desde la base de datos, todos losComment
asociados también se cargan al mismo tiempo.FetchType.LAZY
: Este tipo de carga significa que las entidades relacionadas se cargan a demanda, es decir, cuando se accede a ellas por primera vez. Por ejemplo, si se carga unPost
, losComment
asociados no se cargarán hasta que se acceda a ellos mediantepost.getComments()
.
Aquí hay un ejemplo de cómo se utiliza:
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
private List<Comment> comments;
}
En este ejemplo, los Comment
asociados a un Post
no se cargarán de la base de datos hasta que se invoque post.getComments()
.
La elección de las estrategias de cascada y carga depende de las necesidades específicas de la aplicación y de las consideraciones de rendimiento.
Conclusión
En conclusión, las asociaciones de entidades JPA en Spring Boot proporcionan una forma poderosa y flexible de mapear las relaciones entre las entidades de la base de datos en un modelo de objetos de dominio. Estas asociaciones pueden representar diversas relaciones como One-to-One, One-to-Many, Many-to-One y Many-to-Many.
Las anotaciones como @OneToOne
, @OneToMany
, @ManyToOne
, @ManyToMany
, @JoinColumn
, @JoinTable
, entre otras, facilitan la configuración de estas relaciones. Además, JPA ofrece operaciones en cascada que permiten propagar ciertas operaciones desde una entidad a sus entidades relacionadas, lo que facilita el manejo de las operaciones de base de datos.
Además, JPA proporciona estrategias de carga EAGER y LAZY para optimizar el rendimiento de la base de datos. La estrategia EAGER carga las entidades relacionadas inmediatamente, mientras que la estrategia LAZY las carga a demanda, lo que puede ayudar a mejorar la eficiencia de la aplicación.
Ejercicios de esta lección Asociaciones de entidades JPA
Evalúa tus conocimientos de esta lección Asociaciones de entidades JPA con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
API Query By Example (QBE)
Identificadores y relaciones JPA
Borrar datos de base de datos
Web y Test Starters
Métodos find en repositorios
Controladores Spring MVC
Inserción de datos
CRUD Customers Spring MVC + Spring Data JPA
Backend API REST con Spring Boot
Controladores Spring REST
Uso de Spring con Thymeleaf
API Specification
Registro de usuarios
Crear entidades JPA
Asociaciones en JPA
Asociaciones de entidades JPA
Integración con Vue
Consultas JPQL
Open API y cómo agregarlo en Spring Boot
Uso de Controladores REST
Repositorios reactivos
Inyección de dependencias
Introducción a Spring Boot
CRUD y JPA Repository
Inyección de dependencias
Vista en Spring MVC con Thymeleaf
Servicios en Spring
Operadores Reactivos
Configuración de Vue
Entidades JPA
Integración con Angular
API Specification
API Query By Example (QBE)
Controladores MVC
Anotaciones y mapeo en JPA
Consultas JPQL con @Query en Spring Data JPA
Repositorios Spring Data
Inyección de dependencias
Data JPA y Mail Starters
Configuración de Angular
Controladores Spring REST
Configuración de Controladores MVC
Consultas JPQL con @Query en Spring Data JPA
Actualizar datos de base de datos
Verificar token JWT en peticiones
Login de usuarios
Integración con React
Configuración de React
Todas las lecciones de SpringBoot
Accede a todas las lecciones de SpringBoot y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Spring Boot
Introducción Y Entorno
Spring Boot Starters
Introducción Y Entorno
Inyección De Dependencias
Introducción Y Entorno
Controladores Spring Mvc
Spring Web
Vista En Spring Mvc Con Thymeleaf
Spring Web
Controladores Spring Rest
Spring Web
Open Api Y Cómo Agregarlo En Spring Boot
Spring Web
Servicios En Spring
Spring Web
Clientes Resttemplate Y Restclient
Spring Web
Rxjava En Spring Web
Spring Web
Crear Entidades Jpa
Persistencia Spring Data
Asociaciones De Entidades Jpa
Persistencia Spring Data
Repositorios Spring Data
Persistencia Spring Data
Métodos Find En Repositorios
Persistencia Spring Data
Inserción De Datos
Persistencia Spring Data
Actualizar Datos De Base De Datos
Persistencia Spring Data
Borrar Datos De Base De Datos
Persistencia Spring Data
Consultas Jpql Con @Query En Spring Data Jpa
Persistencia Spring Data
Api Query By Example (Qbe)
Persistencia Spring Data
Api Specification
Persistencia Spring Data
Repositorios Reactivos
Persistencia Spring Data
Introducción E Instalación De Apache Kafka
Mensajería Asíncrona
Crear Proyecto Con Apache Kafka
Mensajería Asíncrona
Creación De Producers
Mensajería Asíncrona
Creación De Consumers
Mensajería Asíncrona
Kafka Streams En Spring Boot
Mensajería Asíncrona
Introducción A Spring Webflux
Reactividad Webflux
Spring Data R2dbc
Reactividad Webflux
Controlador Rest Reactivo Basado En Anotaciones
Reactividad Webflux
Controlador Rest Reactivo Funcional
Reactividad Webflux
Operadores Reactivos Básicos
Reactividad Webflux
Operadores Reactivos Avanzados
Reactividad Webflux
Cliente Reactivo Webclient
Reactividad Webflux
Introducción A Spring Security
Seguridad Con Spring Security
Seguridad Basada En Formulario En Mvc Con Thymeleaf
Seguridad Con Spring Security
Registro De Usuarios
Seguridad Con Spring Security
Login De Usuarios
Seguridad Con Spring Security
Verificar Token Jwt En Peticiones
Seguridad Con Spring Security
Seguridad Jwt En Api Rest Spring Web
Seguridad Con Spring Security
Seguridad Jwt En Api Rest Reactiva Spring Webflux
Seguridad Con Spring Security
Autenticación Y Autorización Con Anotaciones
Seguridad Con Spring Security
Testing Unitario De Componentes Y Servicios
Testing Con Spring Test
Testing De Repositorios Spring Data Jpa
Testing Con Spring Test
Testing Controladores Spring Mvc Con Thymeleaf
Testing Con Spring Test
Testing Controladores Rest Con Json
Testing Con Spring Test
Testing De Aplicaciones Reactivas Webflux
Testing Con Spring Test
Testing De Seguridad Spring Security
Testing Con Spring Test
Testing Con Apache Kafka
Testing Con Spring Test
Integración Con Angular
Integración Frontend
Integración Con React
Integración Frontend
Integración Con Vue
Integración Frontend
En esta lección
Objetivos de aprendizaje de esta lección
- Entender las diferentes tipos de relaciones entre entidades: One-to-One, One-to-Many, Many-to-One y Many-to-Many.
- Aprender a usar las anotaciones para mapear las relaciones entre entidades.
- Conocer cómo se manejan las operaciones en cascada para propagar operaciones desde una entidad a otras relacionadas.
- Comprender las estrategias de carga EAGER y LAZY para optimizar el rendimiento de la base de datos.
- Aplicar las asociaciones de entidades JPA en un proyecto Spring Boot real.