1 de 4
http://darioquintana.com.ar/articles/tutorial-de-nhibernate-primeros-pasos
darioquintana.com.ar
Cdigo de ejemplo
En el siguiente ejemplo ser solamente puntapi inicial para introducirnos en este framework de persistencia, si bien contiene algunos consejos como buenas prcticas pero no es lo
que persigue, por esta razn los ejemplos sern sencillos. De hecho, el modelo posee una clara correspondencia de 1 objeto => 1 tabla, lo cual en la realidad no debe buscarse, ya
que los modelos de dominios y de datos buscan resolver problemas diferentes, y si estamos en presencia de esto, es muy probable que no estemos explotando todo el potencial de
ambos modelos, y por sobre todo de esta herramienta. NHibernate nos da la libertad de realizar un modelo de dominio, y despus mapearlo a un modelo de tablas, y viceversa. El
cdigo de ejemplo lo pueden descargar aqu Dario.NH01.zip
Modelo de Dominio
El modelo de dominio con el cual trabajaremos ser el siguiente:
Modelo relacional
El modelo de datos estar representado por estas tres relaciones (tablas):
20/04/2009 19:23
2 de 4
http://darioquintana.com.ar/articles/tutorial-de-nhibernate-primeros-pasos
darioquintana.com.ar
<property name="Fecha" type="DateTime" not-null="true"/>
<bag name="Lineas" cascade="all-delete-orphan">
<key column="IdFactura"/>
<one-to-many class="LineaFactura"/>
</bag>
</class>
</hibernate-mapping>
Veamos los atributos del archivo. Al comienzo del archivo estamos indicando el nombre del assembly: Dario.NH01, donde van a estar ubicadas las clases. Luego el namespace de
dicha clase. Luego comenzamos a tratar las caractersticas de la clase que queremos mapear con el atributo class, en este caso Factura. Dentro de los tags <class
name="Factura"...> ... </class> vamos a indicar todas las configuraciones de dicha clase. Un atributo que no hemos marcado en el mapping pero que viene activado por
defecto y vale la pena explicarlo es lazy="true". Con esto activamos la carga perezosa, lazy load, de modo que las colecciones no se cargarn hasta que sean utilizadas. Este
funcionamiento se logra mediante un proxy y NH se encarga de manejarlo, para nosotros es transparente (por ahora).
Con el tag <id> vamos a indicarle a NH qu property ser mapear con la clave primaria de la tabla, en este caso la property Id se va a corresponder con la columna IdFactura,
ser de tipo int y para indicar que un objeto se considera como nuevo y no como que ya existe en la base, pondremos el atributo unsaved-value="0". Tambien hemos asignado al
generator el valor identity, con esto le decimos NH que se encargue de generar los valores de la primary key. Si hubiramos querido asignarles nosotros el valor, deberamos
reemplazar por el valor assigned. Luego vamos a decirle que la propiedad Fecha, tiene que corresponderse con la columna Fecha, esto es debido que no hemos indicado el nombre
de la columna con el atributo column, y que va a ser de tipo DateTime. Y con esto ya tenemos suficiente como realizar un ABM (Alta/Baja/Modificacin) de la entidad Factura.
Pero para hacer un poco ms interesante esto, agreguemos la relacin 1:N con la clase LineaFactura. Para esto vamos a utilizar el atributo <bag>. Indicamos que el nombre de la
coleccin se llamar Lineas, y como es bag, esta coleccin podr tener elementos repetidos. Para esto utilizamos una coleccin del tipo IList<LineaFactura>. Cabe destacar que
podemos utilizar otro tipo de colecciones que se encuentran en la librera Iesi.Collections.dll.
Algo a notar en este archivo es la declaracin de la relacin many-to-one para la propiedad Factura y tambin para Producto.
De este modo nos aseguramos de que 2 objetos son iguales si son iguales sus propiedades Id y Factura.
Ya hemos sobrescrito el Equals, ahora debemos hacer lo mismo con GetHashCode, debido a que 2 objetos iguales deben tener un mismo nmero de hash (y 2 objetos distintos
pueden o no tener el mismo nmero de hash). El nmero hash no representa un id, no tiene que ser nico.
Una posible implementacin podra ser:
public override int GetHashCode()
{
return id + 29*factura.GetHashCode();
}
Con este mtodo nos aseguramos que 2 lneas factura devuelvan el mismo nmero al ser iguales. Al trabajar con nmeros primos obtenemos buenas funciones hash. Lo importante
aqu es hacer bien la funcin, la optimizacin de esta funcin queda fuera del alcance del tutorial.
Implementando IEquatable<T>
Todas las entidades implementan IEquatable<T>, esto no es necesario para trabajar con NHibernate, solamente es una manera de hacer que las comparaciones por medio de
Equals se realicen de forma tipada.
ISessionFactory e ISession
Una sesin es un marco de trabajo en el cual NH establece una conversacin entre la aplicacin y el motor de base de datos relacional. Para construir una sesin, representado por
ISession alguien que nos provea la sesin, para esto necesitamos de: ISessionFactory. El ISessionFactory se encarga crear sesiones en nuestra aplicacin. En un momento, la
20/04/2009 19:23
3 de 4
http://darioquintana.com.ar/articles/tutorial-de-nhibernate-primeros-pasos
darioquintana.com.ar
aplicacin puede tener 1 o ms sesiones abiertas. Cada sesin representa un 1er. nivel de cach, los objetos que son trados desde la base, o son guardados desde la aplicacin se
encuentran en la cache de primer nivel. Si se solicita un objeto a la base, primero se busca en la cach, si se encuentra ah el objeto, se lo devuelve a la aplicacin sin solicitarlo al
motor relacional. Sino se encuentra en la cach, se realiza la consulta a la base.
Por lo general debemos tener un ISessionFactory por aplicacin, sera necesario tener ms de uno en el caso de que estemos trabajando con ms de una base de datos a la vez.
En esta configuracin hemos incluido el nombre del assembly donde se encontrarn embebidos los archivos de mapeo, en este caso el assembly es: Dario.NH01.
El cdigo necesario para configurar NH al comienzo de la aplicacin es:
Configuration cfg = new Configuration();
cfg.Configure("hibernate.cfg.xml");
ISessionFactory sesiones = cfg.BuildSessionFactory();
ISession sesion = sesiones.OpenSession();
Primeramente debemos crear un objeto del tipo Configuration, configurarlo mediante Configure("hibernate.cfg.xml") y que se encargue de crear el ISessionFactory, por
medio del mtodo BuildSessionFactory(). Una vez que creamos el objeto sesiones del tipo ISessionFactory, ya podemos comenzar a crear objetos ISession. En este caso
trabajaremos con una sola sesin en la aplicacin: sesion.
Es una buena prctica realizar un singleton del objeto ISessionFactory debido a que es un proceso costoso para la aplicacin, en otras palabras, la ejecucin de
se debe hacer una vez durante la ejecucin.
BuildSessionFactory
Creamos 3 productos y los guardamos en la sesin sesion mediante el mtodo Save. Una vez hecho esto podemos continuar con la creacin de la Factura y sus LineaFactura.
Factura factura = new Factura(DateTime.Now);
factura.Lineas.Add(new LineaFactura(factura, prod1, 2.25m, 5));
factura.Lineas.Add(new LineaFactura(factura, prod2, 3.5m, 1));
factura.Lineas.Add(new LineaFactura(factura, prod3, 5.4m, 10));
sesion.Save(factura);
sesion.Flush();
sesion.Close();
Una vez creada factura, podemos realizar un Save . Notse aqu que hemos guardado la factura, y las lneas tambin se guardaron. Esto es debido a que en el mapping de Factura
hemos configurado el Agregado/Actualizacin/Borrado en cascada mediante la siguiente lnea cascade="all-delete-orphan". Despus de realizar todos las inserciones,
procedemos a realizar Flush() para que se ejecuten las sentencias SQL propiamente dichas contra el servidor, en ese momento se guardan todos nuestros objetos, antes de esto los
objetos permanecan en el objeto sesion (en la cache de 1er. nivel).
Luego de que hemos usado la sesin, liberamos los recursos realizando un Close().
Conclusin
En este tutorial vimos nuestros primeros pasos con NHibernate mediante una simple aplicacin de Consola. Se mostr como crear objetos y como persistirlos, inclusive como
persistir una relacin en cascada de padres e hijos (Factura - LineaFactura).
Consultas y comentarios
NHibernate Hispano - Grupo de Usuario de NHibernate en Espaol
20/04/2009 19:23
4 de 4
http://darioquintana.com.ar/articles/tutorial-de-nhibernate-primeros-pasos
darioquintana.com.ar
20/04/2009 19:23