Uno a uno (bidireccional)

Esta lección es muy similar a la anterior , pero en éste caso la relación entre las clases Profesor y Direccion va a ser bidireccional.

Clases Java

Antes de entrar en cómo se implemente en Hibernate , veamos las clases Java y las tablas que definen la relación uno a uno.

Para nuestro ejemplo vamos a usar las clases:

  • Profesor
  • Direccion

Estas dos clases van a tener una relación uno a uno.

 1: public class Profesor implements Serializable  {
 2:     private int id;
 3:     private String nombre;
 4:     private String ape1;
 5:     private String ape2;
 6:     private Direccion direccion;
 7:
 8:     public Profesor(){
 9:     }
10:
11:     public Profesor(int id, String nombre, String ape1, String ape2) {
12:         this.id = id;
13:         this.nombre = nombre;
14:         this.ape1 = ape1;
15:         this.ape2 = ape2;
16:     }
17: }
18:
19: public class Direccion implements Serializable  {
20:     private int id;
21:     private String calle;
22:     private int numero;
23:     private String poblacion;
24:     private String provincia;
25:     private Profesor profesor;
26:
27:     public Direccion(){
28:     }
29:
30:     public Direccion(int id, String calle, int numero, String poblacion, String provincia) {
31:         this.id = id;
32:         this.calle = calle;
33:         this.numero = numero;
34:         this.poblacion = poblacion;
35:         this.provincia = provincia;
36:     }
37: }

Listado 1.Relación 1 a 1

En el listado 1 podemos ver cómo la clase Profesor tiene una propiedad llamada direccion de la clase Direccion (línea 6) y además la clase Direccion también posee referencia a Profesor ya que hemos definido que la relación es bidireccional desde Profesor hacia Direccion y viceversa.

En la clases Java Profesor y Direccion 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 Direccion y viceversa.

PlantUML Graph

Tablas

La tablas de base de datos quedarían de la siguiente forma:

PlantUML Graph

Podemos apreciar que en el diseño de las tabla de la base de datos ya no existe una columna en Profesor con la clave primaria de Direccion o viceversa ya que si la hubiera sería una relación muchos a uno. Entonces ¿cómo se establece la relación entre las dos filas? Simplemente porque tanto Profesor como Direccion deben tener la misma clave primaria y de esa forma se establece la relación.

Fichero de mapeo ''.hbm.xml''

Al persistir dos clases serán necesarios dos ficheros de persistencia:

  • Profesor.hbm.xml
  • Direccion.hbm.xml

Profesor.hbm.xml

El fichero Profesor.hbm.xml quedará de la siguiente forma

 1: <?xml version="1.0" encoding="UTF-8"?>
 2: <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 3: <hibernate-mapping>
 4:   <class name="ejemplo01.Profesor" >
 5:     <id column="Id" name="id" type="integer"/>
 6:     <property name="nombre" />
 7:     <property name="ape1" />
 8:     <property name="ape2" />
 9:
10:     <one-to-one name="direccion" cascade="all" />
11:
12:   </class>
13: </hibernate-mapping>

Fichero Profesor.hbm.xml

El fichero básicamente contiene lo que se ha explicado en las lecciones anteriores excepto por el tag <one-to-one> de la línea 10.

Tag one-to-one

El tag <one-to-one> se utiliza para definir una relación uno a uno entre las dos clases Java. En su forma más sencilla contiene sólamente dos atributos:

  • name:Este atributo contiene el nombre de la propiedad Java con la referencia al otro objeto con el que forma la relación uno a uno. En nuestro ejemplo es el atributo direccion.
  • cascade: Este atributo indicará a hibernate cómo debe actuar cuando realicemos las operaciones de persistencia de guardar, borrar, leer, etc. En el ejemplo el valor debe ser all indicando que deberemos realizar la misma operación en Profesor que enDireccion.

Más información sobre el atributo cascade en Cascade

Direccion.hbm.xml

El fichero Direccion.hbm.xml quedará de la siguiente forma:

 1: <?xml version="1.0" encoding="UTF-8"?>
 2: <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 3: <hibernate-mapping>
 4:   <class name="ejemplo01.Direccion" >
 5:     <id column="Id" name="id" type="integer"/>
 6:     <property name="calle"/>
 7:     <property name="numero"/>
 8:     <property name="poblacion"/>
 9:     <property name="provincia"/>
10:
11:     <one-to-one name="profesor" cascade="all" />
12:
13:   </class>
14: </hibernate-mapping>

Fichero Direccion.hbm.xml

La clase Direccion también tiene la relación uno a uno hacia profesor.

Anotaciones

Para usar anotaciones 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: import java.io.Serializable;
 2: import javax.persistence.*;
 3:
 4:
 5: @Entity
 6: @Table(name="Profesor")
 7: public class Profesor implements Serializable  {
 8:
 9:     @Id
10:     @Column(name="Id")
11:     private int id;
12:
13:     @Column(name="nombre")
14:     private String nombre;
15:
16:     @Column(name="ape1")
17:     private String ape1;
18:
19:     @Column(name="ape2")
20:     private String ape2;
21:
22:     @OneToOne(cascade=CascadeType.ALL)
23:     @PrimaryKeyJoinColumn
24:     private Direccion direccion;
25: }

Clase Profesor anotada

A la propiedad direccion (línea 24) se han añadido dos anotaciones para indicar la relación uno a uno y que esta relación se implementa mediante la clave primaria.

  • @OneToOne(cascade=CascadeType.ALL): Esta anotación indica la relación uno a uno de las 2 tablas. También indicamos el valor de cascade al igual que en el fichero de hibernate.
  • @PrimaryKeyJoinColumn: Indicamos que la relación entre las dos tablas se realiza mediante la clave primaria.

En caso de no incluir la anotación @PrimaryKeyJoinColumn se producirá un error indicando que falta la columna direccion_Id en la tabla Profesor.

Notar que si utilizamos anotaciones es necesario usar @PrimaryKeyJoinColumn mientras que usando el fichero .hbm.xml no es necesario indicarlo.

Más información sobre el atributo cascade en Cascade

El código de Direccion es similar al anterior.

 1: import java.io.Serializable;
 2: import javax.persistence.Column;
 3: import javax.persistence.Entity;
 4: import javax.persistence.Id;
 5: import javax.persistence.Table;
 6:
 7:
 8: @Entity
 9: @Table(name="Direccion")
10: public class Direccion implements Serializable  {
11:
12:     @Id
13:     @Column(name="Id")
14:     private int id;
15:
16:     @Column(name="calle")
17:     private String calle;
18:
19:     @Column(name="numero")
20:     private int numero;
21:
22:     @Column(name="poblacion")
23:     private String poblacion;
24:
25:     @Column(name="provincia")
26:     private String provincia;
27:
28:     @OneToOne(cascade=CascadeType.ALL)
29:     @PrimaryKeyJoinColumn
30:     private Profesor profesor;
31: }

Clase Direccion anotada

Como en el caso anterior vemos cómo debemos incluir los tags @OneToOne y @PrimaryKeyJoinColumn (Líneas 22 y 23) para establecer la relación entre Direccion y Profesor.

Código Java

Ahora que ya tenemos preparadas las clase Java para que puedan persistirse veamos el código necesario para persistirlas.

 1: Direccion direccion1=new Direccion(3, "Calle de la sarten", 23, "Manises", "Valencia");
 2: Profesor profesor1=new Profesor(3, "Sergio", "Mateo", "Ramis");
 3: profesor1.setDireccion(direccion1);
 4: direccion1.setProfesor(profesor1);
 5:
 6: Direccion direccion2=new Direccion(4, "Calle Luis lamarca", 45, "Torrente", "Valencia");
 7: Profesor profesor2=new Profesor(4, "Paco", "Moreno", "Díaz");
 8: profesor2.setDireccion(direccion2);
 9: direccion2.setProfesor(profesor2);
10:
11:
12: Session session=sessionFactory.openSession();
13: session.beginTransaction();
14:
15: session.save(profesor1);
16: session.save(direccion2);
17:
18: session.getTransaction().commit();
19: session.close();

Persistiendo la clase Profesor

El ejemplo incluye dos casos:

  • Crear un objeto direccion1 y otro profesor1 (líneas 1 y 2), crear las relaciones (líneas 3 y 4) y finalmente en la línea 16 guardar el objeto profesor1.
  • Crear un objeto direccion2 y otro profesor2 (líneas 6 y 7), crear las relaciones (líneas 8 y 9) y finalmente en la línea 17 guardar el objeto direccion2.

En ambos casos el resultado aparente es el mismo , se guarda tanto el objeto Direccion como el objeto Profesor al ser la relación bidireccional aunque realmente los 2 casos no son iguales; veamos ahora el porqué.

En el primer caso, si persistimos un objeto Profesor se inserta directamente dicho objeto en la base de datos por lo que no puede existir ya la fila pero sí que se permite que la Direccion ya exista, actualizándose en dicho caso. Pero en el segundo caso si persistimos el objeto Direccion lo que ocurre es lo contrario, no podrá existir la fila de la dirección pero sí podrá existir la fila del Profesor.

unidades/03_relaciones/02_uno_a_uno_bidireccional.txt · Última modificación: 2016/07/03 20:35 (editor externo)
Ir hasta arriba
CC Attribution-Noncommercial-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0