Manual Hibernate
Manual Hibernate
Manual Hibernate
http://www.javaHispano.org
Copyright (c) 2003, Héctor Suárez González. Este documento puede ser distribuido solo bajo los
términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última
versión se encuentra en http://www.javahispano.org/licencias/).
Manual Hibernate
Manual Hibernate
Presentación del tutorial.
. Logo de Hibernate
8. Conclusiones
9. Posibles ejercicios
1. Capítulos.
NOTA: Esta primera parte es de introducción al concepto de capa de persistencia, por lo tanto es bastante teórica.
Página 2
Manual Hibernate
Esta primera aproximación puede ser útil para proyectos o arquitecturas sin casi clases
de negocio, ya que el mantenimiento del código esta altamente ligado a los cambios en el
modelo de datos relacional de la BBDD, un mínimo cambio implica la revisión de casi todo
el código así como su compilación y nueva instalación en el cliente.
Aunque no podemos desechar su utilidad. El acceso a través de SQL directas puede
ser utilizado de manera puntual para realizar operaciones a través del lenguaje SQL lo
cual seria mucho mas efectivo que la carga de gran cantidad de objetos en memoria. Si
bien un buen motor de persistencia debería implementar mecanismos para ejecutar estas
operaciones masivas sin necesidad de acceder a este nivel.
Una aproximación mas avanzada seria la creación de unas clases de acceso a datos (
DAO Data Acces Object). De esta manera nuestra capa de negocio interactuaría con la
capa DAO y esta sería la encargada de realizar las operaciones sobre la BBDD.
Página 3
Manual Hibernate
contra la BBDD. Por lo tanto Hibernate es el puente entre nuestra aplicación y la BBDD,
sus funciones van desde la ejecución de sentencias SQL a través de JDBC hasta la
creación, modificación y eliminación de objetos persistentes.
2. Qué es hibernate
Hibernate[1] es una capa de persistencia objeto/relacional y un generador de sentencias
sql. Te permite diseñar objetos persistentes que podrán incluir polimorfismo, relaciones,
colecciones, y un gran número de tipos de datos. De una manera muy rápida y optimizada
podremos generar BBDD en cualquiera de los entornos soportados : Oracle, DB2, MySql,
etc.. Y lo más importante de todo, es open source, lo que supone, entre otras cosas, que
no tenemos que pagar nada por adquirirlo.
Uno de los posibles procesos de desarrollo consiste en, una vez tengamos el diseño de
datos realizado, mapear este a ficheros XML siguiendo la DTD de mapeo de Hibernate.
Desde estos podremos generar el código de nuestros objetos persistentes en clases Java
y también crear BBDD independientemente del entorno escogido.
Hibernate se integra en cualquier tipo de aplicación justo por encima del contenedor de
datos. Una posible configuración básica de hibernate es la siguiente:
Página 4
Manual Hibernate
4. Arquitectura Base
Podemos observar como Hibernate utiliza la BBDD y la configuración de los datos para
proporcionar servicios y objetos persistentes a la aplicación que se encuentre justo por
arriba de él.
NOTA: Antes de empezar a escribir una línea debemos tener realizado el análisis de nuestra aplicación y la estructura
de datos necesaria para su implementación.
<Encabezado XML>
<Declaración de la DTD>
<class - Definición de la clase persistente>
<id - Identificador>
<generator - Clase de apoyo a la generación
automática de OID's>
<component - Componentes, son las columnas de la tabla>
Página 5
Manual Hibernate
.
.
<one-to-many / many-to-many - Posibles relaciones con
otras entidades persistentes>
.
.
Página 6
Manual Hibernate
1. vm : Genera identificadores de tipo long, short o int. Que serán únicos dentro
de una JVM.
2. sequence : Utiliza el generador de secuencias de las bases de datos DB2,
PostgreSQL, Oracle, SAP DB, McKoi o un generador en Interbase. El tipo
puede ser long, short o int.
3. hilo : Utiliza un algoritmo hi/lo para generar identificadores del tipo long, short
o int. Estos OID's son únicos para la base de datos en la cual se generan. En
realidad solo se trata de un contador en una tabla que se crea en la BBDD. El
nombre y la columna de la tabla a utilizar son pasados como parámetros, y lo
único que hace es incrementar/decrementar el contador de la columna con
cada nueva creación de un nuevo registro. Así, si por ejemplo decimos tener un
identificador único por clase de objetos persistentes, deberíamos pasar como
parámetro tabla table_OID y como columna el nombre de la clase
myclass_OID.
4. uuid.string : Algoritmo UUID para generar códigos ASCII de 16 caracteres.
Página 7
Manual Hibernate
3. type: Indica el tipo de los datos almacenados. Mirar la sección 3.1.7 Tipos de
datos en Hibernate para ver todos las posibilidades de tipos existentes en
Hibernate.
Página 8
Manual Hibernate
package com.hecsua.enumerations;
import net.sf.hibernate.PersistentEnum
public class Meses implements PersistentEnum {
private final int code;
private Meses(int code) {
this.code = code;
Página 9
Manual Hibernate
}
public static final Meses Enero = new Meses(0);
public static final Meses Febrero = new Meses(1);
public static final Meses Marzo = new Meses(2);
...
public int to Int() {return code;}
public static Meses fromInt(int code){
case 0: return Enero;
case 1: return Febrero;
case 2: return Marzo;
...
default: throw new RuntimeException("Mes no valido.");
}
}
Enlace a java.lang.Collection[5]
Las colecciones de elementos que Hibernate puede tratar como persistentes son :
java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.List, y cualquier array
de elementos o valores persistentes. Propiedades del tipo java.util.Collection o
java.util.List pueden ser persistentes utilizando la semántica de bag.
Las colecciones persistentes no retienen ninguna semántica añadida por la clase
implementada de la interface de colección ( ej :iteradores ordenados de LinkedHashSet).
La propiedad persistente que contenga una colección a de ser un interface del tipo Map,
Set o List; nunca HashMap, TreeSet o ArrayList.Esta restricción es debida a que
Hibernate reemplaza las instancias de Map, Set y List con instancias de sus propias
implementaciones de Map, Set o List.
NOTA: Hay que tener cuidado al comparar las colecciones directamente con ==
Las instancias de una colección son diferenciadas en la BBDD mediante una clave
ajena del objeto relacional al cual pertenecen. Esta clave es denominada la clave de la
colección. Esta clave será mapeada con el tag <key>.Las colecciones pueden contener :
tipos basicos, entidades y componentes. No se pueden crear colecciones de colecciones.
Hay muchos tipos de mapeados de colecciones, que podrán ser útiles en un desarrollo
mas avanzado, pero en este primer tutorial nos centraremos en las relaciones entre las
clases persistentes. Las colecciones one-to-many y many-to-many.
Página 10
Manual Hibernate
6. sort: Especifica una colección con una ordenación natural o con una clase
comparadora dada.
7. order-by: Columna\s de la tabla que definen el orden de iteración. Puede ser
ascendente o descendente.
Página 11
Manual Hibernate
5. Relación n-m
Esta estructura se puede diseñar creando una tabla intermedia que relacione los códigos
de los elementos de A con los elementos de B. Queda claro por tanto que una colección
muchos a muchos se ha de mapear en una tabla a parte con las claves de las dos tablas
como claves ajenas.
Esto lo podríamos mapear como sigue :
En este punto no tenemos una columna extra en B que diga los elementos de B que le
corresponden a un elemento de A. En vez de eso tenemos una tabla nueva A_By_B que
contiene los pares de claves relacionados tanto de A hacia B como de B hacia A. Para
que sea bidireccional tiene que ser declara en el mapeo de la clase B como sigue, de
paso la definimos como el fin de la relación entre las dos tablas. Cualquier otro parámetro,
posible para una colección puede ser utilizado aquí ej: lazy, cascade, etc...
Como en el caso anterior si queremos tener una asociación uno a muchos entre dos
tablas, deberemos mapear correctamente las dos. En una crearemos una relación
one-to-many y en la otra una many-to-one. Una asociación one-to-many de A hacia B
requerirá un nuevo campo en B con el valor del índice de A al que se encuentra asociado.
En la tabla A no será necesario ningún nuevo campo, como observamos en la siguiente
imagen :
6. Relación 1-n
Página 13
Manual Hibernate
Por último si una colección es pasada de un objeto persistente a otro, sus elementos
son movidos de una tabla a la otra. Lo bueno de Hibernate es que no nos tenemos que
preocupar de esto, debemos utilizar las colecciones como normalmente lo hemos hecho.
Desechándolas cuando sea necesario, Hibernate se ocupará de su gestión.
3.3. Componentes.
Un buen diseño relacional necesitará de la composición de objetos. El nombre de la
persona, la dirección, una localidad etc.. son todo estructuras de datos que componen
objetos más grandes. Una componente en Hibernate es un objeto persistente contenido
dentro de la misma tabla de su propietario. ej: Clásico ejemplo del nombre/dirección de
una persona :
Página 14
Manual Hibernate
El diseño del primer recuadro a parte de ser mucho más claro es muy sencillo de mapear,
procedemos de la siguiente manera :
La tabla persona tiene que contener los elementos correspondientes a los objetos name y
adress. Así como al resto de las propiedades de persona. Los tipos de estas propiedades
pueden ser cualquier tipo de los soportados por Hibernate, incluso más componentes
NOTA: Un buen ejercicio, antes de continuar con el siguiente capitulo, podría consistir en realizar el mapeo de Localidad
(País, Provincia o Estado, Localidad, código ) como una componente de Dirección.
, colecciones y relaciones. Por último destacar que cuando un componente es nulo todas
sus propiedades lo son a la hora de guardarlo en la BBDD. En el caso contrario cuando
Página 15
Manual Hibernate
cargamos un objeto a memoria, si todas las propiedades del elemento son nulas el
elemento es nulo.
3.4.1. Traducir este diseño relacional a ficheros XML siguiendo las especificaciones
Hibernate será mucho más sencillo de lo que pueda parecer a primera vista. Para crear el
mapeo de Objeto[3], comenzaremos con la definición del fichero XML[4], mediante las dos
líneas siguientes :
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping
DTD//EN"
"..\..\hibernate\hibernate-mapping-2.0.dtd">
En estas dos líneas declaramos el tipo de codificación del fichero XML así como su
DTD.
Después comenzamos a definir nuestro objeto persistente, abrimos el tag
<hibernate-mapping>.Una muy buena costumbre es definir un objeto por fichero, ya que
hace mucho más legible el código y simplifica su modificación.
3.4.2. El siguiente tag será el class:
Como podéis observar la clase se denominará Objeto y estará dentro del package
com.hecsua.bean. Esta clase hará referencia a la tabla objeto dentro de la BBDD.
3.4.3. El siguiente paso es definir el identificador, el nombre lógico de la propiedad
queremos que sea id, que haga referencia a la columna idObject y es un dato de tipo
long, el resultado es el siguiente :
Para obtener los OID's utilizaremos la clase hilo sobre la tabla uid_table y la columna
next_hi_value :
<generator class="hilo">
<param name="table">uid_table</param>
<param name="column">next_hi_value</param>
</generator>
3.4.5. Ahora definimos las relaciones, como se puede ver son todas del tipo muchos a
uno, por lo que en realidad son columnas de identificadores ajenos a nuestra tabla. Se
definen utilizando la etiqueta many-to-one, el nombre lógico de la propiedad nos ha de
recordar el rol de la relación, el parámetro class deberá ser la clase del objeto asociado y
la columna que almacenara su identificador.
Página 17
Manual Hibernate
3.4.6. Por último tenemos que mapear la relación n-m, esta es una relación circular
entre registros de la tabla objeto. Para mapear esta relación utilizaremos la siguiente
estructura, dejando como se puede observar los identificadores relacionados en la tabla
Obj_By_Obj:
En estas dos relaciones observamos que ambas utilizan la tabla obj_by_obj donde se
guardarán las parejas de identificadores relacionados. Una de ellas ha de ser "inverse",
con esta etiqueta declaramos cual es el final de la relación circular.
Finalmente cerramos las etiquetas, y acabamos de crear nuestro primer mapeo de un
objeto relacional, como podéis observar no es tan complicado como parece, eso sí,
siempre que partamos de un buen diseño será mucho mas fácil. Ahora tan solo resta
definir el resto de los objetos persistentes en sus correspondientes ficheros XML , generar
las clases persistentes asociadas, y comenzar a utilizar Hibernate. Todo esto en el
siguiente capitulo Herramientas, Configuración y Uso de Hibernate.
Aún nos faltarían cosas por hacer, que podeis realizar como ejercicio:
1. Crear y definir ficheros Usuario.hbm.xml, Sistema.hbm.xml y
TipoObjeto.hbm.xml.
2. Modificar Usuario.hbm.xml para que contenga el nombre del usuario, la
dirección ( esta a su vez la localidad ) como componentes.
3. Definir una relación entre Usuario y Sistema. Un Usuario tiene que
pertenecer a un Sistema.
4. Validar mediante DTD de Hibernate que son ficheros XML bien formados
Conclusión
No hemos utilizado ni la mitad de las posibilidades de Hibernate. Este abarca tal
Página 18
Manual Hibernate
Recursos y referencias
[1] Hibernate, http://hibernate.bluemars.net
[2] Guía hacia Hibernate, http://www.javahispano.org/articles.article.action?id=80
[3] Objeto.hbm.xml, Objeto.hbm.xml.sampleObjeto.hbm.xml
[4] Documentación sobre XML, http://www.xml.org
[5] Framework Collection de java, http://java.sun.com
Copyright (c) 2003, Héctor Suárez González. Este documento puede ser distribuido solo bajo los
términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última
versión se encuentra en http://www.javahispano.org/licencias/).
Página 19