Herramientas de usuario

Herramientas del sitio


unidades:04_claves_primarias_y_tipos_datos:03_componentes

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
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();
    }  
}

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.

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.

En el siguiente diagrama UML se ve que la relación es desde Profesor hacia Nombre.

Profesorint idNombreString nombreString ape1String ape2getNombreCompleto()getIniciales()nombre11

Tablas

La tabla de base de datos quedaría de la siguiente forma:

«Table»ProfesorINTEGER idVARCHAR nombreVARCHAR ape1VARCHAR ape2

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:

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>

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:

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;
    }
}

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:

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();
    }    
}

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.

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();

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 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.
unidades/04_claves_primarias_y_tipos_datos/03_componentes.txt · Última modificación: 2023/04/07 21:26 por 127.0.0.1