====== Uno a muchos (ordenada) ======
La relación uno a muchos consiste simplemente en que un objeto //padre// tenga una lista **Ordenar** de otros objetos //hijo// de forma que al persistirse el objeto principal también se persista la lista de objetos //hijo//. Esta relación también suele llamarse //maestro-detalle// o //padre-hijo//.
===== Clases Java =====
Antes de entrar en cómo se implementa en Hibernate , veamos las clases Java y las tablas que definen la relación uno a muchos.
Para nuestro ejemplo vamos a usar las clases:
* ''Profesor''
* ''CorreoElectronico''
Estas dos clases van a tener una relación uno a muchos.
public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private List correosElectronicos;
public Profesor(){
}
public Profesor(int id, String nombre, String ape1, String ape2) {
this.id = id;
this.nombre = nombre;
this.ape1 = ape1;
this.ape2 = ape2;
}
}
public class CorreoElectronico implements Serializable {
private int idCorreo;
private String direccionCorreo;
private Profesor profesor;
public CorreoElectronico() {
}
public CorreoElectronico(int idCorreo,String direccionCorreo,Profesor profesor) {
this.idCorreo=idCorreo;
this.direccionCorreo=direccionCorreo;
this.profesor=profesor;
}
}
En el listado 1 podemos ver cómo la clase ''Profesor'' tiene una propiedad llamada ''correosElectronicos'' de la clase ''CorreoElectronico'' (línea 6) y además la clase ''CorreoElectronico'' también posee referencia a ''Profesor'' ya que hemos definido que la relación es bidireccional desde ''Profesor'' hacia ''Direccion'' y viceversa.
El mecanismo que usamos en Java para almacenar una serie de objetos //hijo// es el interfaz java.util.List|List. Se utiliza este interfaz ya que nos va a permitir que los objetos //hijo// se encuentren ordenados.
En la clases Java ''Profesor'' y ''CorreoElectronico'' no se han incluido los métodos get/set de cada propiedad para facilitar la lectura pero deben estar en la clase Java.
En el siguiente diagrama UML se ve la relación desde ''Profesor'' hacia ''CorreoElectronico'' y viceversa.
class Profesor
Profesor : int id
Profesor : String nombre
Profesor : String ape1
Profesor : String ape2
class CorreoElectronico
CorreoElectronico: int idCorreo
CorreoElectronico: String direccionCorreo
Profesor "1" -- "0..n" CorreoElectronico: correosElectronicos {Ordenada}
===== Tablas =====
La tablas de base de datos quedarían de la siguiente forma:
class Profesor <>
Profesor : INTEGER id
Profesor : VARCHAR nombre
Profesor : VARCHAR ape1
Profesor : VARCHAR ape2
class CorreoElectronico <>
CorreoElectronico: INTEGER idCorreo
CorreoElectronico: VARCHAR direccionCorreo
CorreoElectronico: INTEGER idProfesor
CorreoElectronico: INTEGER idx
Profesor "1" -- "0..n" CorreoElectronico
Podemos ver cómo la tabla ''CorreoElectronico'' contiene como clave ajena la clave primaria de la tabla ''Profesor'' y de esa forma se establece la relación uno a muchos.
Se ha añadido la columna ''idx'' la cual almacenará el orden de los objetos ''hijos'' dentro de la lista. Sin esta columna sería imposible posteriormente saber el orden en el que se encontraban los elementos.
===== Fichero de mapeo ''.hbm.xml'' =====
Al persistir dos clases serán necesarios dos ficheros de persistencia:
* ''Profesor.hbm.xml''
* ''CorreoElectronico.hbm.xml''
==== Profesor.hbm.xml ====
El fichero ''Profesor.hbm.xml'' quedará de la siguiente forma
El fichero básicamente contiene lo que se ha explicado en las lecciones anteriores excepto por el tag '''' (líneas 10 a 17).
=== Tag list ===
El tag '''' se utiliza para definir una relación //uno a muchos// entre las dos clases Java en las cuales hay un orden.
== Atributos ==
* **name**: Es el nombre de la propiedad Java del tipo java.util.Set|Set en la cual se almacenan todos los objetos //hijos//.En nuestro ejemplo el valor es ''correosElectronicos'' ya que es la propiedad que contiene el java.util.Set|Set.
* **cascade**: Como ya hemos explicado en anteriores lecciones, este atributo indica que se realizan las mismas operaciones con el objeto //padre// que con los objetos //hijos//, es decir si un se borra los otros también, etc. Su valor habitual es ''all''.Mas información en [[unidades:03_relaciones:06_cascade]].
* **inverse**: En este caso el atributo ''inverse'' debe tener el valor ''false'' ya que de esa forma se guardará en valor del orden de cada objeto. Si se estableciera a ''true'' no se guardaría el valor.
Recuerda poner el valor del atributo ''inverse'' a ''false''
inverse="false"
== Tags anidados ==
* **key** Este tag contiene otro anidado llamado ''column'' con el atributo ''name'' que indica el nombre de una columna de la base de datos. Esta columna debe ser de la tabla //hijo// y ser el nombre de la clave ajena a la tabla //padre//. En nuestro ejemplo es ''idProfesor'' ya que es el nombre de la clave ajena en la tabla ''CorreoElectronico''.
* **list-index** Este tag contiene otro anidado llamado ''column'' con el atributo ''name'' que indica el nombre de una columna de la base de datos. Esta columna debe ser de la tabla //hijo// y ser la columna donde se guarda el **orden** que ocupa dentro de la lista. En nuestro ejemplo es ''idx''.
* **one-to-many** Este tag contiene el atributo ''class'' con el FQCN de la clase Java //hija//. En nuestro ejemplo es el nombre de la clase ''CorreoElectronico'' cuyo FQCN es ''ejemplo05.CorreoElectronico''.
Podemos pensar que el valor del atributo ''class'' en el tag ''one-to-many'' sea opcional ya que hibernate podría ser capaz de deducirlo como ha hecho en otras ocasiones, sin embargo no es así. En caso de no indicarlo se producirá la siguiente excepción:
org.hibernate.MappingException: Association references unmapped class: null
==== CorreoElectronico.hbm.xml ====
El fichero ''CorreoElectronico.hbm.xml'' quedará de la siguiente forma:
El fichero básicamente contiene lo que se ha explicado en las lecciones anteriores excepto por el tag '''' (líneas 9 a 11).
=== Tag many-to-one ===
El tag '''' se utiliza para definir una relación //muchos a uno// entre las dos clases Java.
== Atributos ==
* **name**: Es el nombre de la propiedad Java que enlaza con el objeto //padre//. En nuestro ejemplo el valor es ''profesor'' ya que es la propiedad que contiene la referencia a la clase ''Profesor''.
== Tags anidados ==
* **column ** Este tag contiene el atributo ''name'' que indica el nombre de una columna de la base de datos. Esta columna debe ser de la tabla //hijo// y ser el nombre de la clave ajena a la tabla //padre//. En nuestro ejemplo es ''idProfesor'' ya que es el nombre de la clave ajena en la tabla ''CorreoElectronico''.
===== Anotaciones =====
Para usar notaciones deberemos modificar el código fuente de las clases Java y no usar los ficheros ''.hbm.xml''.
El código fuente de la clase ''Profesor'' queda de la siguiente forma:
@Entity
@Table(name="Profesor")
public class Profesor implements Serializable {
@Id
@Column(name="Id")
private int id;
@Column(name="nombre")
private String nombre;
@Column(name="ape1")
private String ape1;
@Column(name="ape2")
private String ape2;
@OneToMany(cascade= CascadeType.ALL)
@JoinColumn(name="IdProfesor")
@IndexColumn(name="idx")
private List correosElectronicos;
public Profesor(){
}
public Profesor(int id, String nombre, String ape1, String ape2) {
this.id = id;
this.nombre = nombre;
this.ape1 = ape1;
this.ape2 = ape2;
}
}
A la propiedad ''correosElectronicos'' se ha añadido una anotación para indicar la relación //uno a muchos//.
* **OneToMany**:Como su nombre indica le dice a Hibernate que esta propiedad contendrá la lista de //hijos//.
* **cascade**: Este atributo tiene el mismo significado que el del fichero de mapeo de Hibernate. Mas información en [[unidades:03_relaciones:06_cascade]].
* **JoinColumn**: Indicaremos el nombre de la columna que en la tabla //hija// contiene la clave ajena a la tabla //padre//. En nuestro ejemplo es la columna de la base de datos ''IdProfesor'' que se encuentra en la tabla ''CorreoElectronico'' la cual enlaza con la tabla ''Profesor''.
* **IndexColumn**: Indicaremos el nombre de la columna que en la tabla //hija// contiene el orden dentro de la lista de //hijos//. En nuestro ejemplo es la columna de la base de datos ''idx'' que se encuentra en la tabla ''CorreoElectronico''.
El código de la clase CorreoElectronico es el siguiente:
@Entity
@Table(name="CorreoElectronico")
public class CorreoElectronico implements Serializable {
@Id
@Column(name="IdCorreo")
private int idCorreo;
@Column(name="DireccionCorreo")
private String direccionCorreo;
@ManyToOne
@JoinColumn(name="IdProfesor")
private Profesor profesor;
public CorreoElectronico() {
}
public CorreoElectronico(int idCorreo,String direccionCorreo,Profesor profesor) {
this.idCorreo=idCorreo;
this.direccionCorreo=direccionCorreo;
this.profesor=profesor;
}
}
A la propiedad ''profesor'' se han añadido dos anotaciones para indicar la relación:
* **ManyToOne**:Al ser el otro lado de la relación indicamos que desde este lado es una relación //mucho a uno//.
* **JoinColumn**: Indicaremos el nombre de la columna que en la tabla //hija// contiene la clave ajena a la tabla //padre//. En nuestro ejemplo es la columna de la base de datos ''IdProfesor'' que se encuentra en la tabla ''CorreoElectronico'' la cual enlaza con la tabla ''Profesor''.
====== Código Java ======
Ahora que ya tenemos preparadas las clase Java para que puedan persistirse veamos el código necesario para persistirlas.
Profesor profesor=new Profesor(9, "Rosa", "Díaz", "Del Toro");
List correosElectronicos=new ArrayList<>();
correosElectronicos.add(new CorreoElectronico(3, "rosa@yahoo.com",profesor));
correosElectronicos.add(new CorreoElectronico(2, "rosa@hotmail.com",profesor));
correosElectronicos.add(new CorreoElectronico(1, "rosa@gmail.com",profesor));
profesor.setCorreosElectronicos(correosElectronicos);
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(profesor);
session.getTransaction().commit();
session.close();
La explicación del código es la siguiente:
* En la línea 1 se crea el objeto ''Profesor''
* En la segunda línea se crea el objeto java.util.ArrayList|ArrayList que implementa el interfaz java.util.List|List el cual contendrá la lista de hijos.
* Desde las líneas 3 a la 5 se crean los objetos ''CorreoElectronico'' y se añaden al java.util.List|List.
* En la línea 7 se establece la relación entre la lista de hijos (''CorreoElectronico'') y el padre (''Profesor'').
* En la línea 12 se guarda el objeto ''Profesor'' y automáticamente se guardan también sus hijos.