Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Introduccion A NHibernate
Introduccion A NHibernate
1.- Que es NHibernate y para qu sirve.........................................................................3 2.- Instalacin de NHibernate.........................................................................................6 3.- Configuracin de NHibernate...................................................................................7 4.- Ejemplos sencillos de mapeo OR..............................................................................9 4.1 Mapeo de clases sencillo.......................................................................................11 4.2 Mapeo con herencia...............................................................................................12 4.3 Mapeo de composiciones.......................................................................................16 4.4 Mapeo de relaciones uno a muchos.......................................................................20 4.5 Mapeo de relaciones muchos a muchos................................................................24 5.- Manipulacin de datos persistentes........................................................................26 5.1 Recuperando un objeto de la base de datos. .........................................................26 5.2 Realizando consultas simples................................................................................27
Introduccin a NHibernate
Introduccin a NHibernate
Podemos notar que la aplicacin trabajar con objetos persistentes, pero sin comunicarse directamente con la base de datos. En su lugar, la comunicacin ser con el framework Nhibernate, el cual se compone de una seccin de configuracin (puede ser archivo App.config o Web.config segn nuestro proyecto sea Windows Forms o Web) y un conjunto de mapeos Objeto-Relacionales. Utilizando estos elementos, Nhibernate se comunicar con la base de datos y realizar las acciones requeridas por los objetos persistentes (insercin, actualizacin, borrado, seleccin). Entrando un poco ms en detalle, una arquitectura ligera de NHibernate es cuando la aplicacin proporciona sus propias conexiones ADO.NET y maneja lo que son transacciones, entonces la arquitectura ser:
Introduccin a NHibernate
Los objetos persistentes requieren almacenar estados, para esto es necesario utilizar una sesin (canal de comunicacin entre la aplicacin y la base de datos). La sesin de comunicacin ser creada por una SessionFactory, que es un cach de los mapeos de una base de datos en particular. La SessionFactory puede ser configurada utilizando cdigo o configurando los archivos App.config o Web.config. Ahora, si deseamos utilizar todas las caractersticas que provee NHibernate, podemos utilizar una arquitectura como la que se muestra a continuacin:
En esta arquitectura, NHibernate provee lo que es el control de transacciones (utilizando Transactions creadas por una TransactionFactory) y control de conexiones ADO.NET que no estn expuestas a la aplicacin, sin embargo pueden ser extendidas o implementadas por los desarrolladores. En resumen, NHibernate es un Framework que pretende abstraer por completo al desarrollador de lo que es el manejo de persistencia en las aplicaciones. Al utilizar NHibernate el desarrollador slo trabajar con objetos capaces de almacenar y recuperar estados, con todo lo que ello significa (manejo de relaciones entre objetos, jerarqua de objetos, etc.).
Introduccin a NHibernate
Introduccin a NHibernate
En la zona de configuracin es posible agregar las configuraciones especficas para cada aplicacin utilizada en la solucin actual. En este caso es necesario configurar las opciones de NHibernate para que acceda a la base de datos utilizada. A continuacin un ejemplo de la configuracin de NHibernate para acceder a una base de datos.
<nhibernate> <add key=hibernate.connection.provider value=Nhibernate.Connection.DriverConnectionProvider/> <add key=hibernate.dialect value=Nhibernate.Dialect.XXX /> <add key=hibernate.connection.driver_class value=Nhibernate.Driver.YYY/> <add key=hibernate.connection.connection_string value=ZZZ /> </nhibernate>
Donde se debe reemplazar los valores XXX, YYY y ZZZ segn sea la base de datos que estemos utilizando para almacenar los datos de nuestra aplicacin. La versin 1.2 de Nhibernate soporta las bases de datos ms utilizadas hoy en da. A continuacin se listan algunas de las bases de datos soportadas por Nhibernate 1.2 y los valores de configuracin de las variables XXX, YYY y ZZZ del ejemplo anterior.
Introduccin a NHibernate
Microsoft SQL Server 2000 XXX: MsSql2000Dialect YYY: SqlClientDriver ZZZ: Server=dbServer;Initial catalog=db;Integrated Security=SSPI Microsoft SQL Server 2005 XXX: MsSql2005Dialect YYY: SqlClientDriver ZZZ: Server=Server;Database=EjemplosNHibernate;User Id=usuario;Password=pwd MySQL XXX: MySQLDialect o MySQL5Dialect (MySQL 5) YYY: MySqlDataDriver ZZZ: Server=server;Database=database;User ID=user; Password=password Oracle XXX: OracleDialect / Oracle9Dialect YYY: OracleClientDriver ZZZ: Data Source=fuente;User Id=user;Password=pwd; PostgreSQL XXX: PostgreSQLDialect YYY: NpgslDriver ZZZ: Server=Server;Database=db;User Id=user;Password=pwd; Encoding=UNICODE Teniendo la configuracin del archivo App.config definida, slo nos queda obtener el driver necesario para la conexin y agregar una referencia a l en nuestro proyecto. SQL Server 2000-2005: System.Data.SqlClient en System.Data.dll (VS2005). MySQL: http://dev.mysql.com/downloads/connector/net/1.0.html Oracle: System.Data.OracleClient.dll (en VS2005). PostgreSQL: http://pgfoundry.org/projects/npgsql/
Introduccin a NHibernate
Introduccin a NHibernate
public void Save() { NhibernateManager nhm = new NHibernateManager(); ISession session = NHibernateManager.NHSession; session.Save(this); session.Close(); NHibernateManager.CloseSessionFactory(); } Existe la posibilidad de manejar el acceso a la base de datos en base a transacciones, es decir los cambios en la base de datos se realizan de manera atmica controlados por una transaccin. En caso de suceder alguna anomala durante una transaccin abierta, se puede indicar a la aplicacin que aborte la transaccin y esto anular cualquier posible cambio en la base de datos. Para utilizar transacciones en el mtodo Save de los objetos persistentes se puede utilizar el siguiente cdigo de ejemplo. public void Save() { NhibernateManager nhm = new NHibernateManager(); ISession session = NHibernateManager.NHSession; ITransaction tx = session.Transaction; tx.Begin(); try { session.Save(this); tx.Commit(); } catch { tx.RollBack(); } session.Close(); NHibernateManager.CloseSessionFactory(); } Otro requerimiento para el mapeo Objeto-Relacional es el poseer un archivo de mapeo, este archivo est en formato xml y su nombre por convencin es clasePersistente.hbm.xml. Todo archivo de mapeo debe contener como nodo raz lo siguiente: <hibernate-mapping xmlns=urn:nhibernate-mapping-2.2 namespace=miNamespace assembly=miAssembly default-lazy=false > <class . . . > <!-- mapeo de la clase --> </class> Introduccin a NHibernate 10
</hibernate-mapping> Donde se hace referencia al assembly donde estar contenida la clase mapeada y su archivo de mapeo. Adems se referencia el namespace de la clase mapeada. NHibernate 1.2 considera por defecto la opcin default-lazy=true, lo que requiere que todas las propiedades pblicas de las clases persistentes sean virtuales, si queremos evitar esta opcin seteamos el atributo a false.
CREATE TABLE gato( idCat varchar(32) NOT NULL, name varchar(30) NOT NULL );
Introduccin a NHibernate
11
Teniendo ambas partes del sistema, es decir, la clase persistente y la tabla sql correspondiente a dicha clase, ahora debemos realizar el mapeo de atributos de la clase a columnas de la tabla. Para esto debemos crear un archivo llamado Cat.hbm.xml, que ser el archivo por el cual NHibernate pregunte cuando se requiera guardar un nuevo objeto Cat en la base de datos. Un ejemplo del archivo Cat.hbm.xml para mapear la clase Cat a la base de datos es el que se muestra a continuacin: <class name="Cat" table="gato"> <id name=Id> <column name=idCat sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <property name="Nombre" column="name"/> </class> Teniendo todo esto listo, guardar un objeto Cat en la base de datos es algo tan simple como: Cat tom = new Cat(); tom.Nombre = Tom; tom.Save();
Introduccin a NHibernate
12
public string Id { get { return id; } set { id = value;} } public string Nombre { get { return nombre; } set { nombre = value; } } public int Edad { get { return edad; } set { edad = value; } } Public void Save() { /* implementacion */ } } public class Empleado : Persona { private int sueldo; public int Sueldo{ get { return sueldo; } set { sueldo = value; } } } public class Cliente : Persona { private string tipoCliente; public string TipoCliente{ get { return tipoCliente; } set { tipoCliente = value; } } } La primera estrategia es llamada table-per-class-hierarchy, es decir, en el modelo de datos se tiene slo una tabla por jerarqua de datos, lo que significa que en la base de datos slo habr una tabla llamada, por ejemplo, tblPersona. Esta tabla contendr los campos necesarios para almacenar a la clase persona y todos los campos necesarios para mapear los atributos de toda las subclases de persona, en este caso se requiere que tblPersona agregue los campos sueldo y tipoCliente a su definicin. Un campo extra es requerido para manejar polimorfismo, este campo se conocer como
Introduccin a NHibernate
13
discriminador e indicar a NHibernate a qu clase corresponde una fila particular de la tabla tblPersona. Un ejemplo de la definicin de la tabla tblPersona para la estrategia table-perclass-hierarchy ser: CREATE TABLE tblPersona( idPersona varchar(32) NOT NULL, name varchar(30) NOT NULL, edad int, TipoPersona varchar(255), sueldo int, tipocliente varchar(30) ); En este caso el discriminador ser la columna TipoPersona y ser de tipo string que caracterice a la clase a la cual pertenece la fila correspondiente en la tabla. El discriminador puede ser de cualquier tipo NHibernate. <class name="Persona" table="tblPersona" discriminator-value=PERSONA> <id name=Id> <column name=idPersona sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <discriminator column="TipoPersona" type="String"/> <property name="Nombre" column="name"/> <property name="Edad" column="edad"/> <subclass name="Cliente" discriminator-value="CLIENTE"> <property name="TipoCliente" column="tipocliente"/> </subclass> <subclass name="Empleado" discriminator-value="EMPL"> < property name="Sueldo" column="sueldo"/> </subclass> </class> La segunda estrategia es llamada table-per-subclass que, tal como lo indica, utiliza una tabla por cada clase de la jerarqua. En este caso tendremos las tablas Persona, Cliente y Empleado, las cuales se definen a continuacin. CREATE TABLE Persona( idPersona varchar(32) NOT NULL, name varchar(30) NOT NULL, edad int ); CREATE TABLE Cliente( Introduccin a NHibernate 14
personaId varchar(32) NOT NULL, tipocliente varchar(30) ); CREATE TABLE Empleado( personaId varchar(32) NOT NULL, sueldo int ); Para manejar la relacin de jerarqua entre las clases, es necesario agregar un campo a las tablas Cliente y Empleado que ser una referencia a la fila en la tabla Persona donde estarn sus datos personales. Este campo extra puede ser una clave fornea en la base de datos, pero eso es tarea del DBA, por lo que no se detallar sobre ese tema en esta seccin. Ahora, el mapeo de las clases pertenecientes a esta jerarqua se muestra a continuacin: <class name="Persona" table="Persona"> <id name=Id> <column name=idPersona sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <property name="Nombre" column="name"/> <property name="Edad" column="edad"/> <joined-subclass name="Cliente" table="tblCliente"> <key column="PersonaId"/> <property name="TipoCliente" column="tipocliente"/> </joined-subclass> <joined-subclass name="Empleado" table="tblEmpleado"> <key column="PersonaId"/> <property name="Sueldo" column="sueldo"/> </joined-subclass> </class> Cabe sealar que, por ejemplo, si Persona fuese una clase abstracta, ambas estrategias no sufren cambios, el nico cambio ser que no podremos instanciar un objeto de tipo Persona, pero esta es una restriccin de la OO. En cambio, si optamos por la estrategia table-per-concrete-class tendremos que slo realizaremos mapeos de las clases concretas (no abstractas). Realizado el mapeo OR de la jerarqua Persona, utilizar las clases persistentes es tan simple como: Persona p = new Persona(); p.Nombre = Rosa; p.Edad = 35; p.Save();
Introduccin a NHibernate
15
Empleado e = new Empleado(); e.Nombre = Paulina Mondaca; e.Edad = 24; e.Sueldo = 120000; ((Persona)e).Save(); Empleado e = new Empleado(); c.Nombre = Jorge Garay; c.Edad = 34; c.TipoCliente = basico; ((Persona)c).Save();
Es posible representar esta composicin en una tabla SQL agregando los atributos de la clase Direccin a la tabla que corresponde a la clase Persona. Haciendo esto, nuestra tabla tblPersona quedara de la siguiente manera:
Introduccin a NHibernate
16
Lo que pretende este mapeo es que si una clase contiene a otra, entonces la tabla SQL debe contener un campo de un tipo de dato complejo, lo que se representa como un conjunto de columnas que en realidad corresponden a una misma columna, en este caso las columnas DIR_* corresponden a un tipo de datos complejo (tipo de datos Direccion) y deben tratarse como un todo. Si bien se pierde la relacin de equivalencia directa entre modelos, este mapeo tiene sentido ya que al eliminar una instancia de Persona efectivamente se eliminar la instancia Direccin asociada a dicha Persona. Ahora veremos como llevar a la prctica el mapeo del ejemplo recin expuesto. Para este caso primero debemos crear una clase Direccin, la cual se define a continuacin. public class Direccion { private string region; private string ciudad; private string calle; private int numero; public string Region { get { return region; } set { region = value;} } public string Ciudad { get { return ciudad; } set { ciudad = value;} } public string Calle { get { return calle; } set { calle = value;} }
public int Numero { get { return numero; } set { numero = value;} } } Para representar una composicin de Direccin en la clase Persona, debemos agregar un atributo a Persona que sea de tipo Direccin como se muestra a continuacin. public class Persona Introduccin a NHibernate 17
{ private private private private private private private string id; string rut; string nombre; string apellido; int edad; char sexo; Direccion dir;
/* Implementacion de propiedades pblicas */ } Teniendo estas definiciones para ambas clases ahora slo falta configurar correctamente el archivo Persona.hbm.xml para mapear la clase Persona y su relacin con la clase Direccin. Para indicarle a NHibernate que esta es una relacin de Composicin el contenido de Persona.hbm.xml debe ser similar al siguiente: <class name="Persona" table="tblPersona"> <id name=Id> <column name=PersId sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <property name="Rut" column="rut"/> <property name="Nombre" column="nombre"/> <property name="Apellido" column="apellido"/> ... <component name=dir class=Direccion > <property name=Region column=DIR_REGION/> <property name=Ciudad column=DIR_CIUDAD/> <property name=Calle column=DIR_CALLE/> <property name=Numero column=DIR_NUMERO/> </component> </class> Un ejemplo de cmo crear una nueva persona es el siguiente: Persona p = new Persona(); p.Rut = 15000000-0; p.Nombre = Nombre Persona; p.Apellido = Apellido; p.Edad = 41; p.Sexo = M; p.Dir = new Direccion(); p.Dir.Region = Metropolitana; p.Dir.Ciudad = Santiago; p.Dir.Calle = Agustinas; p.Dir.Numero = 123;
Introduccin a NHibernate
18
4.3.1 Agregacin.
Tambin es posible encontrarse con que una clase A contiene un objeto de una clase B, pero si elimino un objeto de la clase A no se debe borrar el objeto de la clase B asociado al objeto eliminado. Esta relacin en OO se conoce como Agregacin. El siguiente ejemplo representa la relacin entre Persona y Direccin, ahora desde el punto de vista de agregacin
Es posible implementar una agregacin de dos maneras, dependiendo de las propiedades de la agregacin que se requieran. Una relacin 1 a 1 entre las clases: En este caso el objeto agregado slo estar ligado al objeto contenedor, pero al borrar el objeto contenedor no es necesario borrar el objeto agregado. Una relacin n a 1 entre las clases: En este caso el objeto agregado podr estar ligado a cero o ms objetos contenedores. Tambin es posible determinar si al eliminar el objeto agregado se debe eliminar todo objeto que lo contenga (eliminacin en cascada).
Dadas las mismas definiciones de clases vistas para el caso de composicin, entonces necesitamos crear los archivos Persona.hbm.xml y Direccion.hbm.xml. El contenido del archivo de mapeo de Direccion debe ser un mapeo de una clase simple, es decir: <class name="Direccion" table="tblDireccion"> <id name=IdDireccion> <column name=IdDireccion sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <property name=Region column=region/> <property name=Ciudad column=ciudad/> <property name=Calle column=calle/> <property name=Numero column=numero/> </class>
Introduccin a NHibernate
19
Para el caso del mapeo de Persona, en la tabla SQL debemos agregar un campo que sea del mismo tipo que el campo IdDireccion de la tabla tblDireccion, que manejar la relacin entre las tablas (a nivel lgico). Debemos agregar una directiva que indique la relacin que queramos construir entre Persona y Direccin. Para esto mapeamos todos los atributos de manera simple (salvo el atributo direccin) y agregamos el mapeo de Direccin dependiendo del tipo de relacin que queramos construir: Relacin 1 a 1: Agregamos.
<one-to-one name="Dir" class="Direccion" column="IdDireccion" />
Relacin n a 1: Agregamos.
<many-to-one name="Dir" class="Direccion" column="IdDireccion" />
A continuacin se expone un ejemplo del cdigo asociado al modelo de clases: public class Proyecto { private string idProyecto; private string descripcion; public string IdProyecto { get { return idProyecto; } set { idProyecto = value; } } public string Descripcion { get { return descripcion; } set { descripcion = value; } } }
Introduccin a NHibernate
20
Imports Iesi.Collections; public class JefeProyecto { private string idJefeProyecto; private ISet proyectos; //requiere Iesi.Collections public string IdJefeProyecto { get { return idProyecto; } set { idProyecto = value; } } public ISet Proyectos { get { return proyectos; } set { proyectos = value; } } } Las colecciones pueden ser implementadas como Listas, Arreglos, Diccionarios o cualquier clase que implemente la interfaz System.Collections.IDictionary, Systems.Collections.IList o Iesi.Collections.ISet. Esta ltima se encuentra en la librera Iesi.Collections, que se distribuye junto con NHibernate, por lo tanto es necesario agregar la referencia correspondiente a nuestro proyecto. Existe un detalle al implementar una coleccin en una clase y es que en la propiedad la coleccin debe definirse del tipo de la interfaz correspondiente a la clase de coleccin, es decir una propiedad puede ser de tipo IList, IDictionary o ISet pero no, por ejemplo, de tipo Set. Teniendo idea de las posibles definiciones en el cdigo de la clase para los distintos tipos de colecciones ahora es necesario conocer cmo realizar el mapeo entre nuestra clase con coleccin y nuestra base de datos. Para esto, primero es necesario modelar la base de datos, pero esto no es tarea difcil. En el caso que estudiamos, una relacin uno a muchos puede ser representada por una tabla tblJefeProyecto que contenga el id del jefe de proyecto y varias tablas tblProyecto que hagan referencia al id del jefe del proyecto como clave fornea. En pocas palabras un esquema relacional puede ser el siguiente:
Luego, el mapeo de la clase Proyecto se realiza de manera simple, como se muestra en el siguiente cdigo. <class name="Proyecto" table="tblProyecto"> <id name=IdProyecto>
Introduccin a NHibernate
21
<column name=IdProyecto sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <property name=Descripcion column=descripcion/> </class> Por otro lado, el mapeo de la clase JefeProyecto requiere de una etiqueta extra que haga referencia a la relacin entre un jefe de proyecto con varios proyectos. Esta etiqueta depender del tipo de coleccin que se haya implementado. A continuacin el mapeo para la clase JefeProyecto que implementa una coleccin de tipo ISet. <class name="JefeProyecto" table="tblJefeProyecto"> <id name=IdJefeProyecto> <column name=IdJefeProyecto sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <set name="Proyectos"> <key column="idJefeProyecto" /> <one-to-many class="Proyecto" /> </set> </class> Lo que se indica en la etiqueta <set> es el nombre de la propiedad de la coleccin de proyectos. Luego se indica que la relacin entre proyectos y jefe de proyecto se har mediante la columna idJefeProyecto de la tabla asociada a la clase Proyecto. Con esta configuracin es posible crear proyectos y asociarlos a un jefe de proyecto en particular. Un ejemplo de cmo realizar esta accin es el siguiente; JefeProyecto jp = new JefeProyecto(); Jp.Proyectos = new Iesi.Collections.HashedSet(); Proyecto p1 = new Proyecto(); p1.Descripcion = proyecto 1; Proyecto p2 = new Proyecto(); p2.Descripcion = proyecto 2; Proyecto p1 = new Proyecto(); p1.Descripcion = proyecto 3; p1.Save(); p2.Save(); p3.Save(); jp.Proyectos.Add(p1); jp.Proyectos.Add(p2); jp.Proyectos.Add(p3); jp.Save();
Introduccin a NHibernate
22
/* Se puede implementar que en el mtodo Save de JefeProyecto se guarden primero los proyectos y luego el objeto JefeProyecto. */ Eventualmente, la clase Proyecto puede tener el otro extremo de la relacin unoa-muchos, es decir tendr un elemento de relacin muchos-a-uno (como el visto en agregacin). Esto implica agregar una propiedad de tipo JefeProyecto en la clase Proyecto y luego definir el siguiente archivo de mapeo de la clase Proyecto. <class name="Proyecto" table="tblProyecto"> <id name=IdProyecto> <column name=IdProyecto sql-type=char(32) not-null=true/> <generator class=uuid.hex/> </id> <property name=Descripcion column=descripcion/> <many-to-one name=jpId class=JefeProyecto column=IdJefeProyecto/> </class> En este ejemplo, la clase Proyecto tiene un atributo llamado jpId de tipo JefeProyecto, el cual ser una referencia al contenido de la columna IdJefeProyecto de la tabla asociada a la clase JefeProyecto.
<set>, y <bag>. Cada una de estas etiquetas est orientada a soportar un tipo de coleccin en particular. A continuacin se listan las principales caractersticas de cada uno de estos elementos: <list>, <map>
<set>: Coleccin desordenada sin duplicados. Compatible con la interfaz Iesi.Collections.ISet. <list>: Coleccin ordenada, requiere una columna ndice. Compatible con la interfaz System.Collections.IList. <map>: Coleccin que almacena pares de elementos. Compatible con la interfaz System.Collections.IDictionary. <bag>: Coleccin desordenada que permite elementos duplicados. Sirve para representar listas no ordenadas. Tambin es posible utilizar las etiquetas <array> y <primitive-array> pero no se ha encontrando informacin sobre estas etiquetas. Una propiedad importante del mapeo de colecciones de objetos es conocida como inicializacin perezosa o carga perezosa (lazy loading, lazy initialization) . Esta estrategia indica que si un objeto X tiene una coleccin de objetos Y, entonces al recuperar X desde la base de datos, slo se recuperarn las propiedades atmicas de X (tipo String, Int, Char, Boolean, etc) pero no las colecciones de objetos Y asociados a X sino hasta que realmente se quiera utilizar la coleccin de objetos Y. En el caso de JefeProyecto slo se recupera el identificador del jefe de proyecto, y luego, si en algn momento se requiere recorrer la coleccin de proyectos cargo de este jefe de proyecto, slo entonces se recuperar la coleccin de proyectos desde la base de datos. Esta
Introduccin a NHibernate
23
caracterstica se puede definir en el archivo de mapeo indicando elementos <set>, <list>, <map> o <bag>.
lazy=true
en los
Esta relacin muchos a muchos debe ser representada en un modelo relacional aadiendo una tercera tabla que haga de NUB entre Banco y Cliente, es decir esta tercera tabla relacionar a los clientes con los bancos, teniendo plena libertad de relacionar cualquier cliente con cualquier banco (claro sin permitir repeticin).
Teniendo este modelo de clases y su respectivo modelo relacional podemos realizar el mapeo OR cosa de poder persistir nuestras clases. <class name=Banco table=Banco> <id name=ID> <generator class=identity/> </id> <set name=Clientes lazy=true
Introduccin a NHibernate
24
table=Banco_Cliente> <key column=BancoID/> <many-to-many class=Cliente column=ClienteID/> </set> </class> <class name=Cliente table=Cliente> <id name=ID> <generator class=identity/> </id> <property name=Nombre column=Nombre /> <property name=Apellido column=Apellido /> </class> Para explicar cmo se realiza el mapeo muchos-a-muchos veremos en detalle la etiqueta de la coleccin: <set name=Clientes lazy=true table=Banco_Cliente> <key column=BancoID/> <many-to-many class=Cliente column=ClienteID/> </set> La relacin entre Banco y Cliente se realiza buscando una instancia en la tabla Banco_Cliente que contenga en la columna BancoID el identificador del banco y en la columna ClienteID el identificador asociado a la clase Cliente. Las colecciones soportadas por las relaciones muchos-a-muchos son las mismas que para el caso de uno-a-muchos y las reglas de definicin son las mismas (atributos de clase definidos como de tipo de la interfaz correspondiente (ISet, IList, etc.).
Introduccin a NHibernate
25
Introduccin a NHibernate
26
Introduccin a NHibernate
27