Conceptos fundamentales:
Antes de comenzar y para entender bien las diferentes relaciones entre entidades debemos tener claro los siguientes conceptos.
Rol: Define cual de las entidades de la relación es origen y cuál es la entidad destino.
Dirección: Define si la relación entre dos entidades es unidireccional o bidireccional. Es decir, si existe la relación en ambos sentidos o solamente en uno de ellos y en este segundo caso identifica a la entidad origen y destino.
Muchos a Uno
Uno a Uno
La Relación entre Empleado y plaza de parking puede ser definida de este tipo porque un empleado tiene una única plaza de parking y la plaza de parking no puede ser compartida por otro empleado
En este caso utilizamos la anotación @OneToOne en la entidad Empleado en conjunción con la anotación @JoinColum similar a como hemos definido en el caso anterior
Muchos a Muchos con tabla de unión
Relaciones Lazy
Antes de comenzar y para entender bien las diferentes relaciones entre entidades debemos tener claro los siguientes conceptos.
Rol: Define cual de las entidades de la relación es origen y cuál es la entidad destino.
Dirección: Define si la relación entre dos entidades es unidireccional o bidireccional. Es decir, si existe la relación en ambos sentidos o solamente en uno de ellos y en este segundo caso identifica a la entidad origen y destino.
Cardinalidad: Indica la cantidad de entidades que existen en cada lado de la
relación. Puede ser uno o muchos
Ordinalidad: Indica si un atributo es obligatorio o opcional
Columnas de Unión: En términos de base de datos una relación entre dos tablas significa
que una tabla referencia a otra tabla. Una columna que referencia a una clave
primaria de otra tabla se denomina “clave externa”.
En JPA estas columnas las llamamos “columnas de unión” y la anotación
@JoinColum es utilizada para configurar este tipo de columnas
A partir de estos conceptos definimos 4 tipos
principales de relaciones entre entidades:
Relaciones Individuales:
Son aquellas en las que la entidad destino de la relación es única. Es decir “Muchos a Uno” o “Uno a Uno”Muchos a Uno
La
relación entre las entidades Empleados y Departamentos puede ser definida de
este tipo porque Muchos Empleados pueden tener Un Departamento
@ManyToOne
identifica una relación de este tipo y debe aparecer en la entidad origen
La
anotación @ManyToOne identifica siempre el lado propietario de la relación, así
que si hay una “columna de unión” la anotación @JoinColum debe aparecer en esta
misma entidad
El lado propietario de la relación se identifica porque lleva la anotación @JoinColum
El lado inverso o no propietario se identifica porque no lleva esta anotación
@Entity public class Employee { @Id private long id; @ManyToOne @JoinColumn(name="DEPT_ID") private Department department; }
Uno a Uno
La Relación entre Empleado y plaza de parking puede ser definida de este tipo porque un empleado tiene una única plaza de parking y la plaza de parking no puede ser compartida por otro empleado
En este caso utilizamos la anotación @OneToOne en la entidad Empleado en conjunción con la anotación @JoinColum similar a como hemos definido en el caso anterior
@Entity public class Empleado { @Id private long id; @OneToOne @JoinColumn(name="PSPACE_ID") private ParkingSpace parkingSpace; }
Relaciones Bidireccionales: En ocasiones nos puede interesar
convertir la relación anterior en bidireccional de modo que ambas entidades
tengan conocimiento de la otra.
Para conseguirlo debemos añadir de nuevo la anotación @OneToOne en
este caso a la propiedad Empleado de la entidad Parking
Además debemos identificar una de las dos entidades como la
propietaria de la relación. En este caso definimos que la entidad propietaria
va a ser Empleado porque es la dirección de la relación que pensamos que es más
frecuentemente usada pero podríamos hacerlo a la inversa.
El elemento mappedBy se añade a la notación @OneToOne de la entidad no
propietaria (Parking) haciendo referencia al atributo de la entidad propietaria
de la relación (Empleado)
@Entity public class ParkingSpace { @Id private long id; private int lot; private String location; @OneToOne(mappedBy="parkingSpace") private Employee employee; }
Relaciones de Colecciones
Son aquellas en las que la entidad destino de la relación es múltiple. Es decir “Uno a Muchos ” o “Muchos a Muchos”
La
relación entre las entidades Departamentos y Empleados puede ser definida de
este tipo desde el punto de vista de los Departamentos porque Un Departamento
tiene Muchos Empleados.
Normalmente
las relaciones de este tipo son bidireccionales. Es decir por un lado tenemos
una relación Muchos a Uno y para el lado inverso tenemos una relación Uno a
Muchos
El elemento mappedBy se añade a la anotación @OneToMany de la entidad
no propietaria (Departamento) haciendo referencia a la propiedad de la entidad
propietaria de la relación (Empleado)
@Entity public class Department { @Id private long id; private String name; @OneToMany(mappedBy="department") private Collection<employee> employees; }
- La entidad propietaria de la
relación debe ser la anotada con @ManyToOne y por tanto debe también llevar
la anotación @JoinColumn
- La entidad no propietaria
debe utilizar el elemento mappedBy para hacer referencia al atributo de la
entidad propietaria
NOTA: Un error típico es no especificar el
elemento mappedBy en la anotación @OneToMany. Esto provoca que el proveedor de
persistencia trate la relación como si fuera unidireccional
La relación entre Empleados y Proyectos en los que trabaja es una ejemplo
de relación Muchos a Muchos.
La Entidad de Empleados tiene una colección de entidades proyecto con la
que se relaciona y viceversa
- En este caso la anotación @ManyToMany en los dos entidades define esta relación.
- NO existe anotación @JoinColumn en ninguno de los dados de la relación y por tanto no tenemos forma de identificar cual es la entidad propietaria.
- En este caso debemos elegir una de las dos entidades, cualquiera nos sirve para utilizar el elemento mappedBy.
NOTA: Un error típico es
no especificar el elemento mappedBy en ninguna de las dos entidades. Esto
provoca que el proveedor de persistencia trate la relación como si fuera
unidireccional
@Entity public class Employee { @Id private long id; private String name; @ManyToMany private Collection<project> projects; } @Entity public class Project { @Id private long id; private String name; @ManyToMany(mappedBy="projects") private Collection<employee> employees; }
Muchos a Muchos con tabla de unión
Podemos definir
una relación Muchos a Muchos utilizando una tercera tabla de unión entre ellas de
modo que relacione ambas entidades. Esta tercera tabla la llamamos “tabla de
unión” y también puede utilizarse en otros tipos de relación pero es menos
común
Un tabla de unión
consiste simplemente en una tabla con dos “claves externas” también llamadas “columnas
de unión” que referencia a cada una de las dos entidades de la relación
La anotación @JoinTable
define la configuración de la tabla de unión. La columna de unión del lado
propietario es definada con el elemento joinColumns y la columna de unión del
lado no propietario con el elemento inverseJoinColumns
@Entity public class Employee { @Id private long id; private String name; @ManyToMany @JoinTable(name="EMP_PROJ", joinColumns=@JoinColumn(name="EMP_ID"), inverseJoinColumns=@JoinColumn(name="PROJ_ID")) private Collection<project> projects; }
Al
igual que para propiedades para las relaciones se puede especificar el modo en
el que la colección de entidades relacionadas es recuperada (Fetch)
En
el caso de las colecciones el uso que vayamos a dar a nuestras entidades
debemos de tenerlo en cuenta para seleccionar un modo impaciente (Eager) o
perezoso (Lazy).
En
los propiedades el modo por defecto es impaciente mientras que en las
colecciones el modo por defecto es perezoso.
@Entity public class Employee { @Id private long id; @OneToOne(fetch=FetchType.LAZY) private ParkingSpace parkingSpace; }
Resumen
En este
artículo hemos analizado en profundidad las relaciones entre tablas que podemos
encontrarnos en una base de datos relacional; para cada una de ellas hemos
visto ejemplos que nos ayudan a comprender como configurar en JPA estas
relaciones y también hemos analizado los principales aspectos que debemos tener
en cuenta en la configuración de nuestras entidades.
Continua aprendiendo…
En el
siguiente artículo aprenderás sobre las operaciones de persistencia sobre
nuestras entidades, conoceremos el lenguaje de consultas JPQL y como utilizarlo con numerosos ejemplos
No hay comentarios:
Publicar un comentario