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.
1 | Listado 1.Relación 1 a n
public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private List< CorreoElectronico> 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 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
El fichero Profesor.hbm.xml
quedará de la siguiente forma
1| Fichero Profesor.hbm.xml
<?xml version ="1.0" encoding ="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name ="ejemplo05.Profesor" >
<id column ="Id" name ="id" type ="integer" />
<property name ="nombre" />
<property name ="ape1" />
<property name ="ape2" />
<list name ="correosElectronicos" cascade ="all" inverse ="false" >
<key>
<column name ="idProfesor" />
</key>
<list-index>
<column name ="Idx" />
</list-index>
<one-to-many class ="ejemplo07.CorreoElectronico" />
</list>
</class>
</hibernate-mapping>
El fichero básicamente contiene lo que se ha explicado en las lecciones anteriores excepto por el tag <list>
(líneas 10 a 17).
Tag list
El tag <list>
se utiliza para definir una relación uno a muchos entre las dos clases Java en las cuales hay un orden.
Atributos
Recuerda poner el valor del atributo
inverse
a
false
inverse="false"
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:
1| Fichero CorreoElectronico.hbm.xml
<?xml version ="1.0" encoding ="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name ="ejemplo05.CorreoElectronico" >
<id column ="IdCorreo" name ="idCorreo" type ="integer" />
<property name ="direccionCorreo" />
<many-to-one name ="profesor" >
<column name ="idProfesor" />
</many-to-one>
</class>
</hibernate-mapping>
El fichero básicamente contiene lo que se ha explicado en las lecciones anteriores excepto por el tag <many-to-one>
(líneas 9 a 11).
Tag many-to-one
El tag <many-to-one>
se utiliza para definir una relación muchos a uno entre las dos clases Java.
Atributos
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:
1 | Clase profesor anotada
@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< CorreoElectronico> 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
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:
1 | Clase CorreoElectronico anotada
@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.
1 | Persistiendo la clase Profesor
Profesor profesor= new Profesor( 9 , "Rosa" , "Díaz" , "Del Toro" ) ;
List< CorreoElectronico> 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
ArrayList que implementa el interfaz
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
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.
unidades/03_relaciones/04_uno_a_muchos_ordenada.txt · Última modificación: 2023/04/07 21:26 por 127.0.0.1
Herramientas de la página