Herramientas de usuario

Herramientas del sitio


unidades:04_claves_primarias_y_tipos_datos:03_componentes

Diferencias

Muestra las diferencias entre dos versiones de la página.


unidades:04_claves_primarias_y_tipos_datos:03_componentes [2023/04/07 21:26] (actual) – creado - editor externo 127.0.0.1
Línea 1: Línea 1:
 +====== Componentes ======
 +Los componentes permiten que varias clases relacionadas se almacenen en una única tabla de la base de datos. Es similar a la relación //uno a uno// desde el punto de vista de Java pero en la base de datos sólo hay una tabla.
  
 +===== Clases Java =====
 +Antes de entrar en cómo se implemente en Hibernate , veamos las clases Java y las tablas que definen la relación.
 +
 +Para nuestro ejemplo vamos a usar las clases:
 +
 +  * Profesor
 +  * Nombre
 +
 +<code java 1>
 +public class Profesor implements Serializable  {
 +    private int id;
 +    private Nombre nombre;
 +    
 +    public Profesor(){ 
 +    }
 +
 +    public Profesor(int id, Nombre nombre) {
 +        this.id = id;
 +        this.nombre=nombre;
 +    }
 +}
 +
 +public class Nombre implements Serializable {
 +    private String nombre;
 +    private String ape1;
 +    private String ape2;
 +    
 +    public Nombre() {
 +        
 +    }
 +
 +    public Nombre(String nombre, String ape1, String ape2) {
 +        this.nombre = nombre;
 +        this.ape1 = ape1;
 +        this.ape2 = ape2;
 +    }
 +    
 +    public String getNombreCompleto() {
 +        StringBuilder sb=new StringBuilder();
 +        if ((ape1!=null) && (ape1.trim().length()>0)) {
 +            sb.append(ape1);
 +        }        
 +        if ((ape2!=null) && (ape2.trim().length()>0)) {
 +            if (sb.length()>0) {
 +                sb.append(" ");
 +            }
 +            sb.append(ape2);
 +        }         
 +        if ((nombre!=null) && (nombre.trim().length()>0)) {
 +            if (sb.length()>0) {
 +                sb.append(",");
 +            }
 +            sb.append(nombre);
 +        }
 +       
 +        
 +        return sb.toString();
 +    }
 +    
 +    public String getIniciales() {
 +        StringBuilder sb=new StringBuilder();
 +        if ((nombre!=null) && (nombre.trim().length()>0)) {
 +            sb.append(nombre.substring(0,1));
 +        }
 +        if ((ape1!=null) && (ape1.trim().length()>0)) {
 +            sb.append(ape1.substring(0,1));
 +        }        
 +        if ((ape2!=null) && (ape2.trim().length()>0)) {
 +            sb.append(ape2.substring(0,1));
 +        }        
 +        
 +        return sb.toString().toUpperCase();
 +    }  
 +}
 +
 +</code>
 +
 +Lo que hemos hecho es extraer las propiedades ''nombre'', ''ape1'' y ''ape2'' en una nueva clase llamada ''Nombre''. ¿Para qué hacer este cambio? Para justificarlo hemos añadido los métodos ''getNombreCompleto()'' y ''getIniciales()''. Si no creáramos la nueva clase ''Nombre'' sería necesario volver a crear estos métodos en cualquier otra entidad que necesite el nombre.
 +
 +<note important>En la clases Java ''Profesor'' y ''Nombre'' no se han incluido los métodos get/set de cada propiedad para facilitar la lectura pero deben estar en la clase Java.</note>
 +
 +En el siguiente diagrama UML se ve que la relación es desde ''Profesor'' hacia ''Nombre''.
 +
 +<uml>
 +class Profesor 
 +Profesor : int id
 +
 +
 +
 +class Nombre
 +Nombre : String nombre
 +Nombre : String ape1
 +Nombre : String ape2
 +Nombre : getNombreCompleto()
 +Nombre : getIniciales()
 +
 +Profesor "1" --> "1" Nombre : nombre 
 +</uml>
 +
 +===== Tablas =====
 +La tabla de base de datos quedaría de la siguiente forma:
 +
 +<uml>
 +class Profesor <<Table>>
 +Profesor : INTEGER id
 +Profesor : VARCHAR nombre
 +Profesor : VARCHAR ape1
 +Profesor : VARCHAR ape2
 +</uml>
 +
 +Podemos apreciar que en el diseño de las tabla de la base de datos no existe ninguna tabla ''Nombre'' aunque sí que existe la clase Java ''Nombre''
 +
 +===== Fichero de mapeo ''.hbm.xml'' =====
 +Al persistir las dos clases será necesario un único fichero de persistencia:
 +  * ''Profesor.hbm.xml''
 +
 +==== Profesor.hbm.xml ====
 +El fichero ''Profesor.hbm.xml'' quedará de la siguiente forma:
 +
 +<code xml 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="ejemplo04.Profesor" >
 +    <id column="Id" name="id" type="integer"/>
 +    
 +    <component name="nombre">    
 +        <property name="nombre" />
 +        <property name="ape1" />
 +        <property name="ape2" />
 +    </component>
 +
 +  </class>
 +</hibernate-mapping>
 +</code>
 +
 +
 +El fichero básicamente es muy sencillo excepto por el nuevo tag ''component'' de la línea 7.
 +
 +=== Tag component ===
 +El tag ''<component>'' se utiliza para especificar que la propiedad Java de la clase se persistirá en la propia tabla de la clase principal. En su forma más sencilla contiene sólo un atributo:
 +  * ''name'':Este atributo contiene el nombre de la propiedad Java con la referencia al otro objeto con el que forma la relación. En nuestro ejemplo es el atributo ''nombre''.
 +
 +===== 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:
 +
 +<code java 1| Clase Profesor anotada >
 +@Entity
 +@Table(name="Profesor")
 +public class Profesor implements Serializable  {
 +    
 +    @Id
 +    @Column(name="Id")
 +    private int id;
 +    @Embedded
 +    private Nombre nombre;
 +    
 +
 +    public Profesor(){ 
 +    }
 +
 +    public Profesor(int id, Nombre nombre) {
 +        this.id = id;
 +        this.nombre=nombre;
 +    }
 +}
 +</code>
 +
 +En la línea 8 se ha incluido la anotación ''@Embedded''.
 +
 +  * **@Embedded**: Esta anotación se usa para indicar que la propiedad ''nombre'' se guardará en la misma tabla que ''Profesor''.
 +
 +La clase Java ''Nombre'' quedará de la siguiente forma:
 +
 +<code java 1| Clase Nombre anotada >
 +@Embeddable
 +public class Nombre implements Serializable {
 +    
 +    @Column(name="nombre")
 +    private String nombre;
 +    
 +    @Column(name="ape1")
 +    private String ape1;
 +    
 +    @Column(name="ape2")
 +    private String ape2;
 +    
 +    public Nombre() {
 +        
 +    }
 +
 +    public Nombre(String nombre, String ape1, String ape2) {
 +        this.nombre = nombre;
 +        this.ape1 = ape1;
 +        this.ape2 = ape2;
 +    }
 +
 +    
 +    
 +    public String getNombreCompleto() {
 +        StringBuilder sb=new StringBuilder();
 +        if ((ape1!=null) && (ape1.trim().length()>0)) {
 +            sb.append(ape1);
 +        }        
 +        if ((ape2!=null) && (ape2.trim().length()>0)) {
 +            if (sb.length()>0) {
 +                sb.append(" ");
 +            }
 +            sb.append(ape2);
 +        }         
 +        if ((nombre!=null) && (nombre.trim().length()>0)) {
 +            if (sb.length()>0) {
 +                sb.append(",");
 +            }
 +            sb.append(nombre);
 +        }
 +       
 +        
 +        return sb.toString();
 +    }
 +    
 +    public String getIniciales() {
 +        StringBuilder sb=new StringBuilder();
 +        if ((nombre!=null) && (nombre.trim().length()>0)) {
 +            sb.append(nombre.substring(0,1));
 +        }
 +        if ((ape1!=null) && (ape1.trim().length()>0)) {
 +            sb.append(ape1.substring(0,1));
 +        }        
 +        if ((ape2!=null) && (ape2.trim().length()>0)) {
 +            sb.append(ape2.substring(0,1));
 +        }        
 +        
 +        return sb.toString().toUpperCase();
 +    }    
 +}
 +</code>
 +
 +A nivel de clase se ha incluido en la línea 1 el atributo ''@Embeddable''.
 +
 +  * **@Embeddable**:Se usa para indicar que esta clase se usará como un componente y que se guardará en la misma tabla que la clase que la posee.
 +===== Código Java =====
 +Ahora que ya tenemos preparadas las clase Java para que puedan persistirse veamos el código necesario para persistirlas.
 +
 +<code java 1 | Persistiendo la clase Profesor>
 +Profesor profesor=new Profesor(410, new Nombre("Gabriel", "Sáez", "Izquierdo"));
 +
 +Session session=sessionFactory.openSession();
 +session.beginTransaction();
 +
 +session.save(profesor);
 +
 +session.getTransaction().commit();
 +session.close();
 +</code>
 +
 +Como podemos ver, el usar componentes no añade ningún tipo de complejidad al código Java que se usa.
 +
 +===== Diferencias =====
 +Veamos ahora qué diferencias hay entre crear una relación [[unidades:03_relaciones:01_uno_a_uno_direccional|uno a uno]] y el uso de componentes.
 +
 +  * En una relación //uno a uno// las 2 clases Java se almacenan en tablas distintas mientras que en un componente lo hace en la misma tabla.
 +  * En una relación //uno a uno// las 2 clases Java deben incluir la referencia a la clave primaria que ambas comparten mientras que en un componente sólo necesita clave primaria la clase //principal// y no el componente.
 +  * En una relación //uno a uno// es posible persistir cualquiera de las 2 clases y se guardará la otra pero en un componente sólo se puede persistir la clase principal y no el componente.