Revista Informática

JPA - Las Relaciones

Publicado el 07 enero 2016 por Miguel Miguel Gómez Cuesta @mgomezcuesta
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.Cardinalidad: Indica la cantidad de entidades que existen en cada lado de la relación. Puede ser uno o muchosOrdinalidad: Indica si un atributo es obligatorio o opcionalColumnas 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

Las Relaciones:

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 UnoLa 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 entidadJPA - Las Relaciones
El lado propietario de la relación se identifica porque lleva la anotación @JoinColumEl 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
JPA - Las Relaciones

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 usado para 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”Uno a MuchosLa 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
JPA - Las Relaciones
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 
Muchos a Muchos

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

JPA - Las Relaciones
  • 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únUn 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
JPA - Las Relaciones
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;
}


Relaciones Lazy

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

Volver a la Portada de Logo Paperblog