Está en la página 1de 27

Introduccin a NHibernate

Francisco Daines O. 20/01/2007

1.- Que es NHibernate y para qu sirve.........................................................................3 2.- Instalacin de NHibernate.........................................................................................6 3.- Con i!uracin de NHibernate..................................................................................." #.- $%e&plos sencillos de &apeo '(..............................................................................) 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 *.- +anipulacin de datos persistentes........................................................................26 5.1 Recuperando un ob e!o de la base de da!os. .........................................................26 5.2 Reali"ando consul!as simples................................................................................27

#n!roducci$n a %&iberna!e

1.- Que es NHibernate y para qu sirve.


'l desarrollo de aplicaciones u!ili"ando el paradi(ma OO es cada )e" m*s adop!ado por empresas de desarrollo de so+!,are- .a /ue pro)ee una (ran can!idad de )en!a as /ue o!ros paradi(mas de desarrollo no permi!en de +orma sencilla. De manera an*lo(a- nanie puede ne(ar el dominio absolu!o del modelo relacional en el mundo de las bases de da!os. 'l problema an(ular es /ue al u!ili"ar OO con 0DR se pierde (ran par!e de la abs!racci$n /ue pro)ee la 1OO. 2laramen!e el impac!o puede )ariar dependiendo de la es!ra!e(ia /ue se u!ilice para comunicar nues!ras clases con las !ablas de un modelo relacional. 'n el peor de los casos- cada clase del sis!ema se comunicar* con la 0DRcreando una dependencia direc!a en!re el modelo OO . el modelo relacional. 's!o si(ni+ica /ue si reali"o un simple cambio- como cambiar el nombre a una !abla- es!o a+ec!a direc!amen!e el c$di(o escri!o en una (ran can!idad de l3neas de- /ui"*s- una (ran can!idad de clases. 1or lo /ue la p4rdida de !iempo es no!able. '5is!en al!erna!i)as al modelo relacional- son las emer(en!es 0ases de Da!os Orien!adas a Ob e!os- las cuales !raba an direc!amen!e con ob e!os . en muchos casos pro)een accesos para una (ran can!idad de len(ua es de pro(ramaci$n !ales como 2667a)a . la pla!a+orma M8.%'9. :dem*s de ser escasas- la ma.or3a de es!as bases de da!os es!*n en )ersiones de !es!in(- por lo /ue implemen!ar es!as bases de da!os si(ni+ica un ries(o /ue muchas empresas no es!*n dispues!as a correr. &as!a hace un !iempo la !area de comunicar OO con 0DR era di+3cil- lue(o- con la creaci$n del modelo D:O ;Da!a :ccess Ob ec!< se simpli+ic$ el asun!o- de+iniendo /ue ser3an s$lo al(unos ob e!os los /ue se comunicar3an con la 0DR- disminu.endo no!oriamen!e el impac!o de reali"ar cambios en la 0ase de Da!os. 1ero !oda)3a no era posible ob!ener independencia en!re el c$di(o de las clases . el acceso a la base de da!os. &ace un par de a=os se liber$ la primera )ersi$n de un Frame,or> de persis!encia llamado NHibernate- una implemen!aci$n para el Microsoft .Net FrameWork de Hiberna!e ;implemen!ado ori(inalmen!e s$lo para 7a)a<. 0ueno pero ?@u4 es precisamen!e %&iberna!eA . ?1ara /u4 u!ili"ar %&iberna!eA son al(unas de las pre(un!as /ue !ra!ar4 de responder a con!inuaci$n. %&iberna!e es un Frame,or> de persis!encia- es decir pro)ee herramien!as /ue +acili!an la !area de persis!ir ob e!os ;i.e. almacenar el es!ado de un ob e!o con el +in de recuperarlo en el +u!uro<. Ba mo!i)aci$n principal de %&iberna!e es abs!raer por comple!o al desarrollador de la base de da!os asociada al pro.ec!o en desarrollo- es decir- el desarrollador debe pensar /ue s$lo !raba a con ob e!os- los cuales puede (uardar en una base de da!os u!ili"ando m4!odos de los mismos ob e!os- pero nunca escribir ni anali"ar una sen!encia 8@B en su c$di(o. Ba ar/ui!ec!ura de %&iberna!e se puede represen!ar de una manera simple como el si(uien!e dia(ramaC

#n!roducci$n a %&iberna!e

1odemos no!ar /ue la aplicaci$n !raba ar* con ob e!os persis!en!es- pero sin comunicarse direc!amen!e con la base de da!os. 'n su lu(ar- la comunicaci$n ser* con el +rame,or> %hiberna!e- el cual se compone de una secci$n de con+i(uraci$n ;puede ser archi)o App.config o Web.config se(Dn nues!ro pro.ec!o sea Eindo,s Forms o Eeb< . un con un!o de mapeos Ob e!oFRelacionales. G!ili"ando es!os elemen!os- %hiberna!e se comunicar* con la base de da!os . reali"ar* las acciones re/ueridas por los ob e!os persis!en!es ;inserci$n- ac!uali"aci$n- borrado- selecci$n<. 'n!rando un poco m*s en de!alle- una ar/ui!ec!ura Hli(eraI de %&iberna!e es cuando la aplicaci$n proporciona sus propias cone5iones :DO.%'9 . mane a lo /ue son !ransacciones- en!onces la ar/ui!ec!ura ser*C

#n!roducci$n a %&iberna!e

Bos ob e!os persis!en!es re/uieren almacenar es!ados- para es!o es necesario u!ili"ar una sesi$n ;canal de comunicaci$n en!re la aplicaci$n . la base de da!os<. Ba sesi$n de comunicaci$n ser* creada por una SessionFactory- /ue es un cach4 de los mapeos de una base de da!os en par!icular. Ba SessionFactory puede ser con+i(urada u!ili"ando c$di(o o con+i(urando los archi)os App.config o Web.config. :hora- si deseamos u!ili"ar !odas las carac!er3s!icas /ue pro)ee %&iberna!epodemos u!ili"ar una ar/ui!ec!ura como la /ue se mues!ra a con!inuaci$nC

'n es!a ar/ui!ec!ura- %&iberna!e pro)ee lo /ue es el con!rol de !ransacciones ;u!ili"ando Transactions creadas por una TransactionFactory< . con!rol de cone5iones :DO.%'9 /ue no es!*n e5pues!as a la aplicaci$n- sin embar(o pueden ser e5!endidas o implemen!adas por los desarrolladores. 'n resumen- %&iberna!e es un Frame,or> /ue pre!ende abs!raer por comple!o al desarrollador de lo /ue es el mane o de persis!encia en las aplicaciones. :l u!ili"ar %&iberna!e el desarrollador s$lo !raba ar* con ob e!os capaces de almacenar . recuperar es!ados- con !odo lo /ue ello si(ni+ica ;mane o de relaciones en!re ob e!os- erar/u3a de ob e!os- e!c.<.

#n!roducci$n a %&iberna!e

2.- Instalacin de NHibernate.


%&iberna!e es una librer3a ;.dll< /ue se u!ili"a con Microsoft Visual Studio .NET. :c!ualmen!e la )ersi$n 1.0.3 es stable . sopor!a las carac!er3s!icas del .Net Frame ork !.! ;J8 2003<. 9ambi4n e5is!e la )ersi$n 1.2.0 beta- desarrollada con el ob e!i)o de brindar sopor!e a !odas las carac!er3s!icas del .Net Frame ork ".# ;J8 2005<. :mbas )ersiones de %&iberna!e se pueden ob!ener desde la p*(ina o+icial del pro.ec!o ;h!!pC//nhiberna!e.source+or(e.ne!<. '5is!e un pa/ue!e de e5!ensiones llamado %hiberna!e 2on!rib disponible para la )ersi$n 1.0.2 de %&iberna!e- /ue o+rece carac!er3s!icas e5!ra a las o+recidas en el pa/ue!e ori(inal de %&iberna!e. &o. en d3a s$lo e5is!e el pa/ue!e 2on!rib para la )ersi$n 1.0.2 de %&iberna!e. 0ueno- una )e" ob!enido el pa/ue!e de %&iberna!e deseado ;)iene en un archi)o ."ip< es necesario descomprimir el archi)o en al(Dn direc!orio del disco duro. 1ara !raba ar con %&iberna!e desde un pro.ec!o de J8 2003 o 2005 s$lo es necesario a(re(ar re+erencias a las si(uien!es librer3as de %&iberna!eC NHibernate.dll Bas si(uien!es librer3as son de u!ilidad en los pro.ec!os /ue implemen!en el +rame,or> %hiberna!e. lo!#net.dll, 1ermi!e con!rolar un log de los e)en!os ocurridos duran!e la e ecuci$n de una aplicaci$n. 's!e log puede almacenarse en un archi)o plano o en una base de da!os. Iesi.Collections.dll, #mplemen!a al(unas colecciones- como 8e!s- /ue no es!*n disponibles en el .%'9 Frame,or>. 'n es!e momen!o nues!ro pro.ec!o es!* lis!o para poder u!ili"ar las carac!er3s!icas del Frame,or> %&iberna!e.

#n!roducci$n a %&iberna!e

3.- Confi uracin de NHibernate.


2omo bien sabemos- la idea de u!ili"ar %&iberna!e es +acili!ar la in!eracci$n en!re ob e!os . !ablas en un modelo de da!os relacional. 8i bien- el desarrollador no in!erac!Da direc!amen!e con la base de da!os- %hiberna!e s3 lo hace- por lo /ue es necesario indicar en un archi)o de con+i(uraci$n cu*l ser* la base de da!os a u!ili"ar . c$mo conec!arse con dicha base de da!os. '5is!en )arias +ormas de con+i(urar la comunicaci$n en!re %&iberna!e . la base de da!os- sin embar(o la m*s recomendable es u!ili"ar un archi)o App.config ;con+i(uraci$n de pro.ec!o< .a /ue permi!e cambiar la con+i(uraci$n de acceso sin cambiar el c$di(o de la aplicaci$n en s3. Gn archi)o de con+i(uraci$n de aplicaciones es un archi)o KMB /ue permi!e con+i(urar al(unas opciones espec3+icas de la aplicaci$n /ue desarrollamos. Ba es!ruc!ura b*sica del archi)o de con+i(uraci$n App.config es la si(uien!e.
<?xml version=1.0 encoding=utf-8?> <configuration> <configSections> <section name=nhibernate t !e=S stem."onfiguration.#ame$alueSection%andler& S stem& $ersion=1.0.'000.0&"ulture=neutral& (ublic)e *o+en=b,,a'c'-1./0e08. 1> <1configSections> <nhibernate> <2-- configuraci3n de nhibernate --> <1nhibernate> <1configuration>

'n la "ona de con+i(uraci$n es posible a(re(ar las con+i(uraciones espec3+icas para cada aplicaci$n u!ili"ada en la soluci$n ac!ual. 'n es!e caso es necesario con+i(urar las opciones de %&iberna!e para /ue acceda a la base de da!os u!ili"ada. : con!inuaci$n un e emplo de la con+i(uraci$n de %&iberna!e para acceder a una base de da!os.
<nhibernate> <add +e =hibernate.connection.!rovider value=#hibernate."onnection.4river"onnection(rovider1> <add +e =hibernate.dialect value=#hibernate.4ialect.555 1> <add +e =hibernate.connection.driver6class value=#hibernate.4river.7771> <add +e =hibernate.connection.connection6string value=888 1> <1nhibernate>

Donde se debe reempla"ar los )alores $$$- %%% . &&& se(Dn sea la base de da!os /ue es!emos u!ili"ando para almacenar los da!os de nues!ra aplicaci$n. Ba )ersi$n 1.2 de %hiberna!e sopor!a las bases de da!os m*s u!ili"adas ho. en d3a. : con!inuaci$n se lis!an al(unas de las bases de da!os sopor!adas por %hiberna!e 1.2 . los )alores de con+i(uraci$n de las )ariables $$$- %%% . &&& del e emplo an!erior.

#n!roducci$n a %&iberna!e

+icroso t -Q. -erver 2/// 000, Ms8/l2000Dialec! 111, 8/l2lien!Dri)er 222, 38er)erLdb8er)erM#ni!ial ca!alo(LdbM#n!e(ra!ed 8ecuri!.L881#I +icroso t -Q. -erver 2//* 000, Ms8/l2005Dialec! 111, 8/l2lien!Dri)er 222, H8er)erL8er)erMDa!abaseL' emplos%&iberna!eMGser #dLusuarioM1ass,ordLp,dI +y-Q. 000, M.8@BDialec! o M.8@B5Dialec! ;M.8@B 5< 111, M.8/lDa!aDri)er 222, H8er)erLser)erMDa!abaseLda!abaseMGser #DLuserM 1ass,ordLpass,ordI 'racle 000, OracleDialec! / OracleNDialec! 111, Oracle2lien!Dri)er 222, HDa!a 8ourceL+uen!eMGser #dLuserM1ass,ordLp,dMI 4ost!re-Q. 000, 1os!(re8@BDialec! 111, %p(slDri)er 222, H8er)erL8er)erMDa!abaseLdbMGser #dLuserM1ass,ordLp,dM 'ncodin(LG%#2OD'I 9eniendo la con+i(uraci$n del archi)o App.config de+inida- s$lo nos /ueda ob!ener el dri)er necesario para la cone5i$n . a(re(ar una re+erencia a 4l en nues!ro pro.ec!o. -Q. -erver 2///-2//*, 8.s!em.Da!a.8/l2lien! en 8.s!em.Da!a.dll ;J82005<. +y-Q., h!!pC//de).m.s/l.com/do,nloads/connec!or/ne!/1.0.h!ml 'racle, 8.s!em.Da!a.Oracle2lien!.dll ;en J82005<. 4ost!re-Q., h!!pC//p(+oundr..or(/pro ec!s/np(s/l/

#n!roducci$n a %&iberna!e

!.- "#e$plos sencillos de $apeo %&.


%&iberna!e permi!e la implemen!aci$n de )arios modelos de dise=o para la persis!encia de ob e!os- por !an!o se puede op!ar por u!ili"ar ob e!os 'A(- pa!r$n AbstractFactory- en!re o!ros. 8e recomienda crear una clase /ue con!role la creaci$n de sesiones . acceso a la base de da!os- lue(o- se(Dn sea el modelo de ob e!os /ue u!ilicemos- llamaremos a es!a clase desde los ob e!os Sa)e*+- ,pdate*+- e!c. de cada ob e!o /ue mane e persis!encia en la base de da!os. 's recomendable cons!ruir una clase mana(er de la cone5i$n a la base de da!oses!a clase mane ar* la creaci$n de sesiones para poder reali"ar las operaciones de bDs/ueda- inserci$n- ac!uali"aci$n . eliminaci$n. : con!inuaci$n se presen!a un e emplo del c$di(o de la clase NHibernateManager /ue u!ili"aremos en los e emplos de es!a secci$n. !ublic class #%ibernate9anager:; < !rivate static =session>actor nh>actor ? !rivate static "onfiguration nh"onfig? static void #%ibernate9anager:; < nh"onfig = ne@ "onfiguration:;? nh"onfig.AddAssembl :B#ombreAssembl ;? nh>actor = nh"onfig.CuildSession>actor :;? D !ublic static =session #%Session < get < return nh>actor .E!enSession:;? D D !ublic static void "loseSession>actor :; < =f : nh>actor 2= null ; nh>actor ."lose:;? D D 's!a clase nos permi!ir* crear una nue)a cone5i$n a la base de da!os . asociar una sesi$n a dicha cone5i$n. :n!es de )er los e emplos b*sicos de almacenamien!o de ob e!os persis!en!es . su correspondien!e mapeo ob e!oFrelacional )amos a necesi!ar implemen!ar el m4!odo 8a)e en cada ob e!o persis!en!e. 'l con!enido de es!e m4!odo se mues!ra a con!inuaci$n.

#n!roducci$n a %&iberna!e

!ublic void Save:; < #hibernate9anager nhm = ne@ #%ibernate9anager:;? =Session session = #%ibernate9anager.#%Session? session.Save:this;? session."lose:;? #%ibernate9anager."loseSession>actor :;? D '5is!e la posibilidad de mane ar el acceso a la base de da!os en base a !ransacciones- es decir los cambios en la base de da!os se reali"an de manera a!$mica con!rolados por una !ransacci$n. 'n caso de suceder al(una anomal3a duran!e una !ransacci$n abier!a- se puede indicar a la aplicaci$n /ue abor!e la !ransacci$n . es!o anular* cual/uier posible cambio en la base de da!os. 1ara u!ili"ar !ransacciones en el m4!odo 8a)e de los ob e!os persis!en!es se puede u!ili"ar el si(uien!e c$di(o de e emplo. !ublic void Save:; < #hibernate9anager nhm = ne@ #%ibernate9anager:;? =Session session = #%ibernate9anager.#%Session? =*ransaction tx = session.*ransaction? tx.Cegin:;? tr < session.Save:this;? tx."ommit:;? D catch < tx.FollCac+:;? D session."lose:;? #%ibernate9anager."loseSession>actor :;? D O!ro re/uerimien!o para el mapeo Ob e!oFRelacional es el poseer un archi)o de mapeo- es!e archi)o es!* en +orma!o -ml . su nombre por con)enci$n es clase.ersistente./bm.-ml. 9odo archi)o de mapeo debe con!ener como nodo ra3" lo si(uien!eC <hibernate-ma!!ing xmlns=urnGnhibernate-ma!!ing-H.H names!ace=mi#ames!ace assembl =miAssembl default-laI =false > <class . . . > <2-- ma!eo de la clase --> <1class> #n!roducci$n a %&iberna!e 10

<1hibernate-ma!!ing> Donde se hace re+erencia al assembl. donde es!ar* con!enida la clase mapeada . su archi)o de mapeo. :dem*s se re+erencia el namespace de la clase mapeada. %&iberna!e 1.2 considera por de+ec!o la opci$n default0la1y23true3- lo /ue re/uiere /ue !odas las propiedades pDblicas de las clases persis!en!es sean )ir!uales- si /ueremos e)i!ar es!a opci$n se!eamos el a!ribu!o a false.

4.1 Mapeo de clases sencillo.


'l primer e emplo /ue )eremos ser* crear una clase persis!en!e simple- es decires!a clase no !endr* relaciones de nin(Dn !ipo ;asociaci$n- a(re(aci$n- e!c.< con o!ra clase. %ues!ra clase de e emplo se(uir* siendo 4at- la cual .a posee el m4!odo Sa)e de+inido recien!emen!e. 8i nues!ra clase 4at es!* de+inida como si(ueC !ublic class "at < !rivate string id? !rivate string nombre? !ublic string =d < get < return id? D set < id = value? D D !ublic string #ombre < get < return nombre? D set < nombre = value? D D !ublic void Save:; < 1J im!lementacion J1 D D
4onde el identificador del gato serK un string de ti!o hash :/H caracteres;& entonces nuestra tabla SLM debe estar definida como sigueG

"FNA*N *ACMN gato: id"at varchar:/H; #E* #OMM& name varchar:/0; #E* #OMM ;?

#n!roducci$n a %&iberna!e

11

9eniendo ambas par!es del sis!ema- es decir- la clase persis!en!e . la !abla s/l correspondien!e a dicha clase- ahora debemos reali"ar el mapeo de a!ribu!os de la clase a columnas de la !abla. 1ara es!o debemos crear un archi)o llamado 4at./bm.-ml- /ue ser* el archi)o por el cual %&iberna!e pre(un!e cuando se re/uiera (uardar un nue)o ob e!o 4at en la base de da!os. Gn e emplo del archi)o 4at./bm.-ml para mapear la clase 4at a la base de da!os es el /ue se mues!ra a con!inuaci$nC <class name=P"atP table=PgatoP> <id name==d> <column name=id"at sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <!ro!ert name=P#ombreP column=PnameP1> <1class> 9eniendo !odo es!o lis!o- (uardar un ob e!o 2a! en la base de da!os es al(o !an simple comoC "at tom = ne@ "at:;? tom.#ombre = B*om? tom.Save:;?

4.2 Mapeo con herencia.


%&iberna!e permi!e 3 es!ra!e(ias para mane o de persis!encia de erar/u3as de clases. Bas es!ra!e(ias permi!idas sonC table0per0class0/ierarc/y table0per0subclass table0per0concrete0class ;polimor+ismo impl3ci!o< 1ara e+ec!os de es!e documen!o s$lo se )er*n las es!ra!e(ias table0per0class0 /ierarc/y . table0per0subclass. 8upon(amos /ue !enemos el si(uien!e e emplo. Gna empresa necesi!a mane ar la in+ormaci$n personal !an!o de sus empleados como de sus clien!es- por lo !an!o (enera un modelo er*r/uico- donde e5is!e una clase .ersona /ue con!iene los da!os personales . subclases Empleado . 4liente /ue con!ienen los de!alles re/ueridos para empleados . clien!es. Ba de+inici$n de clases se mues!ra a con!inuaci$n. !ublic class (ersona < !rivate string id? !rivate string nombre? !rivate int edad?

#n!roducci$n a %&iberna!e

12

!ublic string =d < get < return id? D set < id = value?D D !ublic string #ombre < get < return nombre? D set < nombre = value? D D !ublic int Ndad < get < return edad? D set < edad = value? D D (ublic void Save:; < 1J im!lementacion J1 D D !ublic class Nm!leado G (ersona < !rivate int sueldo? !ublic int Sueldo< get < return sueldo? D set < sueldo = value? D D D !ublic class "liente G (ersona < !rivate string ti!o"liente? !ublic string *i!o"liente< get < return ti!o"liente? D set < ti!o"liente = value? D D D Ba primera es!ra!e(ia es llamada table0per0class0/ierarc/y- es decir- en el modelo de da!os se !iene s$lo una !abla por erar/u3a de da!os- lo /ue si(ni+ica /ue en la base de da!os s$lo habr* una !abla llamada- por e emplo- tbl.ersona. 's!a !abla con!endr* los campos necesarios para almacenar a la clase persona . !odos los campos necesarios para mapear los a!ribu!os de !oda las subclases de persona- en es!e caso se re/uiere /ue tbl.ersona a(re(ue los campos sueldo . tipo4liente a su de+inici$n. Gn campo e5!ra es re/uerido para mane ar polimor+ismo- es!e campo se conocer* como

#n!roducci$n a %&iberna!e

13

discriminador e indicar* a %&iberna!e a /u4 clase corresponde una +ila par!icular de la !abla tbl.ersona. Gn e emplo de la de+inici$n de la !abla !bl1ersona para la es!ra!e(ia table0per0 class0/ierarc/y ser*C "FNA*N *ACMN tbl(ersona: id(ersona varchar:/H; #E* #OMM& name varchar:/0; #E* #OMM& edad int& *i!o(ersona varchar:H'';& sueldo int& ti!ocliente varchar:/0; ;? 'n es!e caso el discriminador ser* la columna Tipo.ersona . ser* de !ipo s!rin( /ue carac!erice a la clase a la cual per!enece la +ila correspondien!e en la !abla. 'l discriminador puede ser de cual/uier !ipo %&iberna!e. <class name=P(ersonaP table=Ptbl(ersonaP discriminator-value=(NFSE#A> <id name==d> <column name=id(ersona sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <discriminator column=P*i!o(ersonaP t !e=PStringP1> <!ro!ert name=P#ombreP column=PnameP1> <!ro!ert name=PNdadP column=PedadP1> <subclass name=P"lienteP discriminator-value=P"M=N#*NP> <!ro!ert name=P*i!o"lienteP column=Pti!oclienteP1> <1subclass> <subclass name=PNm!leadoP discriminator-value=PN9(MP> < !ro!ert name=PSueldoP column=PsueldoP1> <1subclass> <1class> Ba se(unda es!ra!e(ia es llamada table0per0subclass /ue- !al como lo indicau!ili"a una !abla por cada clase de la erar/u3a. 'n es!e caso !endremos las !ablas .ersona- 4liente . Empleado- las cuales se de+inen a con!inuaci$n. "FNA*N *ACMN (ersona: id(ersona varchar:/H; #E* #OMM& name varchar:/0; #E* #OMM& edad int ;? "FNA*N *ACMN "liente: #n!roducci$n a %&iberna!e 14

!ersona=d varchar:/H; #E* #OMM& ti!ocliente varchar:/0; ;? "FNA*N *ACMN Nm!leado: !ersona=d varchar:/H; #E* #OMM& sueldo int ;? 1ara mane ar la relaci$n de erar/u3a en!re las clases- es necesario a(re(ar un campo a las !ablas 4liente . Empleado /ue ser* una re+erencia a la +ila en la !abla .ersona donde es!ar*n sus da!os personales. 's!e campo e5!ra puede ser una cla)e +or*nea en la base de da!os- pero eso es !area del D0:- por lo /ue no se de!allar* sobre ese !ema en es!a secci$n. :hora- el mapeo de las clases per!enecien!es a es!a erar/u3a se mues!ra a con!inuaci$nC <class name=P(ersonaP table=P(ersonaP> <id name==d> <column name=id(ersona sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <!ro!ert name=P#ombreP column=PnameP1> <!ro!ert name=PNdadP column=PedadP1> <Roined-subclass name=P"lienteP table=Ptbl"lienteP> <+e column=P(ersona=dP1> <!ro!ert name=P*i!o"lienteP column=Pti!oclienteP1> <1Roined-subclass> <Roined-subclass name=PNm!leadoP table=PtblNm!leadoP> <+e column=P(ersona=dP1> <!ro!ert name=PSueldoP column=PsueldoP1> <1Roined-subclass> <1class> 2abe se=alar /ue- por e emplo- si 1ersona +uese una clase abs!rac!a- ambas es!ra!e(ias no su+ren cambios- el Dnico cambio ser* /ue no podremos ins!anciar un ob e!o de !ipo 1ersona- pero es!a es una res!ricci$n de la OO. 'n cambio- si op!amos por la es!ra!e(ia table0per0concrete0class !endremos /ue s$lo reali"aremos mapeos de las clases concre!as ;no abs!rac!as<. Reali"ado el mapeo OR de la erar/u3a 1ersona- u!ili"ar las clases persis!en!es es !an simple comoC (ersona ! = ne@ (ersona:;? !.#ombre = BFosa? !.Ndad = /'? !.Save:;?

#n!roducci$n a %&iberna!e

15

Nm!leado e = ne@ Nm!leado:;? e.#ombre = B(aulina 9ondaca? e.Ndad = H0? e.Sueldo = 1H0000? ::(ersona;e;.Save:;? Nm!leado e = ne@ Nm!leado:;? c.#ombre = BSorge Tara ? c.Ndad = /0? c.*i!o"liente = Bbasico? ::(ersona;c;.Save:;?

4.3 Mapeo de composiciones.


Gna composici$n corresponde a una relaci$n unoFaFuno en!re dos clases donde al eliminar la ins!ancia de la clase con!enedora se elimina la ins!ancia de la clase compues!a. Ba e/ui)alencia en modelo relacional de es!a relaci$n en!re clases se )e ma!eriali"ada como una a(re(aci$n de columnas en la !abla principal de los a!ribu!os de la clase con!enida. : con!inuaci$n se presen!a un e emplo de una composici$n de clases.

's posible represen!ar es!a composici$n en una !abla 8@B a(re(ando los a!ribu!os de la clase 'irecci5n a la !abla /ue corresponde a la clase .ersona. &aciendo es!o- nues!ra !abla tbl.ersona /uedar3a de la si(uien!e maneraC

#n!roducci$n a %&iberna!e

16

Bo /ue pre!ende es!e mapeo es /ue si una clase con!iene a o!ra- en!onces la !abla 8@B debe con!ener un campo de un !ipo de da!o comple o- lo /ue se represen!a como un con un!o de columnas /ue en realidad corresponden a una misma columna- en es!e caso las columnas '6789 corresponden a un !ipo de da!os comple o ;!ipo de da!os 'ireccion< . deben !ra!arse como un !odo. 8i bien se pierde la relaci$n de e/ui)alencia direc!a en!re modelos- es!e mapeo !iene sen!ido .a /ue al eliminar una ins!ancia de .ersona e+ec!i)amen!e se eliminar* la ins!ancia 'irecci5n asociada a dicha 1ersona. :hora )eremos como lle)ar a la pr*c!ica el mapeo del e emplo reci4n e5pues!o. 1ara es!e caso primero debemos crear una clase 'irecci5n: la cual se de+ine a con!inuaci$n. !ublic class 4ireccion < !rivate string region? !rivate string ciudad? !rivate string calle? !rivate int numero? !ublic string Fegion < get < return region? D set < region = value?D D !ublic string "iudad < get < return ciudad? D set < ciudad = value?D D !ublic string "alle < get < return calle? D set < calle = value?D D

!ublic int #umero < get < return numero? D set < numero = value?D D D 1ara represen!ar una composici$n de 'irecci5n en la clase .ersona- debemos a(re(ar un a!ribu!o a .ersona /ue sea de !ipo 'irecci5n como se mues!ra a con!inuaci$n. !ublic class (ersona #n!roducci$n a %&iberna!e 17

< !rivate !rivate !rivate !rivate !rivate !rivate !rivate string id? string rut? string nombre? string a!ellido? int edad? char sexo? 4ireccion dir?

1J =m!lementacion de !ro!iedades !Ublicas J1 D 9eniendo es!as de+iniciones para ambas clases ahora s$lo +al!a con+i(urar correc!amen!e el archi)o .ersona./bm.-ml para mapear la clase .ersona . su relaci$n con la clase 'irecci5n. 1ara indicarle a %&iberna!e /ue es!a es una relaci$n de 2omposici$n el con!enido de .ersona./bm.-ml debe ser similar al si(uien!eC <class name=P(ersonaP table=Ptbl(ersonaP> <id name==d> <column name=(ers=d sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <!ro!ert name=PFutP column=PrutP1> <!ro!ert name=P#ombreP column=PnombreP1> <!ro!ert name=PA!ellidoP column=Pa!ellidoP1> ... <com!onent name=dir class=4ireccion > <!ro!ert name=Fegion column=4=F6FNT=E#1> <!ro!ert name="iudad column=4=F6"=O4A41> <!ro!ert name="alle column=4=F6"AMMN1> <!ro!ert name=#umero column=4=F6#O9NFE1> <1com!onent> <1class> Gn e emplo de c$mo crear una nue)a persona es el si(uien!eC (ersona ! = ne@ (ersona:;? !.Fut = B1'000000-0? !.#ombre = B#ombre (ersona? !.A!ellido = BA!ellido? !.Ndad = 01? !.Sexo = B9? !.4ir = ne@ 4ireccion:;? !.4ir.Fegion = B9etro!olitana? !.4ir."iudad = BSantiago? !.4ir."alle = BAgustinas? !.4ir.#umero = 1H/?

#n!roducci$n a %&iberna!e

1O

. . . 11 guardar obReto !. !.Save:;?

!.3.1 ' re acin.


9ambi4n es posible encon!rarse con /ue una clase : con!iene un ob e!o de una clase 0- pero si elimino un ob e!o de la clase : no se debe borrar el ob e!o de la clase 0 asociado al ob e!o eliminado. 's!a relaci$n en OO se conoce como :(re(aci$n. 'l si(uien!e e emplo represen!a la relaci$n en!re 1ersona . Direcci$n- ahora desde el pun!o de )is!a de a(re(aci$n

's posible implemen!ar una a(re(aci$n de dos maneras- dependiendo de las propiedades de la a(re(aci$n /ue se re/uieran. 5na relacin 1 a 1 entre las clases, 'n es!e caso el ob e!o Ha(re(adoI s$lo es!ar* li(ado al ob e!o con!enedor- pero al borrar el ob e!o con!enedor no es necesario borrar el ob e!o a(re(ado. 5na relacin n a 1 entre las clases, 'n es!e caso el ob e!o a(re(ado podr* es!ar li(ado a cero o m*s ob e!os con!enedores. 9ambi4n es posible de!erminar si al eliminar el ob e!o a(re(ado se debe eliminar !odo ob e!o /ue lo con!en(a ;eliminaci$n en cascada<.

Dadas las mismas de+iniciones de clases )is!as para el caso de composici$nen!onces necesi!amos crear los archi)os .ersona./bm.-ml . 'ireccion./bm.-ml. 'l con!enido del archi)o de mapeo de 'ireccion debe ser un mapeo de una clase simple- es decirC <class name=P4ireccionP table=Ptbl4ireccionP> <id name==d4ireccion> <column name==d4ireccion sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <!ro!ert name=Fegion column=region1> <!ro!ert name="iudad column=ciudad1> <!ro!ert name="alle column=calle1> <!ro!ert name=#umero column=numero1> <1class>

#n!roducci$n a %&iberna!e

1N

1ara el caso del mapeo de 1ersona- en la !abla 8@B debemos a(re(ar un campo /ue sea del mismo !ipo /ue el campo 6d'ireccion de la !abla tbl'ireccion- /ue mane ar* la relaci$n en!re las !ablas ;a ni)el l$(ico<. Debemos a(re(ar una direc!i)a /ue indi/ue la relaci$n /ue /ueramos cons!ruir en!re .ersona . 'irecci5n. 1ara es!o mapeamos !odos los a!ribu!os de manera simple ;sal)o el a!ribu!o direcci$n< . a(re(amos el mapeo de 'irecci5n dependiendo del !ipo de relaci$n /ue /ueramos cons!ruirC (elacin 1 a 1, :(re(amos.
<one-to-one name=P4irP class=P4ireccionP column=P=d4ireccionP 1>

(elacin n a 1, :(re(amos.
<man -to-one name=P4irP class=P4ireccionP column=P=d4ireccionP 1>

4.4 Mapeo de relaciones uno a muchos.


'l si(uien!e es un e emplo de una clase /ue con!iene una colecci$n de ob e!os de o!ra clase . la relaci$n es uno a muc/os. Gn 7e+e de 1ro.ec!o puede mane ar uno o m*s pro.ec!os a la )e"- . un pro.ec!o debe es!ar asociado a un 7e+e de 1ro.ec!o.

: con!inuaci$n se e5pone un e emplo del c$di(o asociado al modelo de clasesC !ublic class (ro ecto < !rivate string id(ro ecto? !rivate string descri!cion? !ublic string =d(ro ecto < get < return id(ro ecto? D set < id(ro ecto = value? D D !ublic string 4escri!cion < get < return descri!cion? D set < descri!cion = value? D D D

#n!roducci$n a %&iberna!e

20

=m!orts =esi."ollections? !ublic class Sefe(ro ecto < !rivate string idSefe(ro ecto? !rivate =Set !ro ectos? 11reQuiere =esi."ollections !ublic string =dSefe(ro ecto < get < return id(ro ecto? D set < id(ro ecto = value? D D !ublic =Set (ro ectos < get < return !ro ectos? D set < !ro ectos = value? D D D Bas colecciones pueden ser implemen!adas como Bis!as- :rre(los- Diccionarios o cual/uier clase /ue implemen!e la in!er+a" System.4ollections.6'ictionary: Systems.4ollections.6;ist o 6esi.4ollections.6Set. 's!a Dl!ima se encuen!ra en la librer3a #esi.2ollec!ions- /ue se dis!ribu.e un!o con %&iberna!e- por lo !an!o es necesario a(re(ar la re+erencia correspondien!e a nues!ro pro.ec!o. '5is!e un de!alle al implemen!ar una colecci$n en una clase . es /ue en la propiedad la colecci$n debe de+inirse del !ipo de la in!er+a" correspondien!e a la clase de colecci$n- es decir una propiedad puede ser de !ipo 6;ist- 6'ictionary o 6Set pero no- por e emplo- de !ipo 8e!. 9eniendo idea de las posibles de+iniciones en el c$di(o de la clase para los dis!in!os !ipos de colecciones ahora es necesario conocer c$mo reali"ar el mapeo en!re nues!ra clase con colecci$n . nues!ra base de da!os. 1ara es!o- primero es necesario modelar la base de da!os- pero es!o no es !area di+3cil. 'n el caso /ue es!udiamos- una relaci$n uno a muchos puede ser represen!ada por una !abla tbl<efe.royecto /ue con!en(a el id del e+e de pro.ec!o . )arias !ablas tbl.royecto /ue ha(an re+erencia al id del e+e del pro.ec!o como cla)e +or*nea. 'n pocas palabras un es/uema relacional puede ser el si(uien!eC

Bue(o- el mapeo de la clase .royecto se reali"a de manera simple- como se mues!ra en el si(uien!e c$di(o. <class name=P(ro ectoP table=Ptbl(ro ectoP> <id name==d(ro ecto>

#n!roducci$n a %&iberna!e

21

<column name==d(ro ecto sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <!ro!ert name=4escri!cion column=descri!cion1> <1class> 1or o!ro lado- el mapeo de la clase <efe.royecto re/uiere de una e!i/ue!a e5!ra /ue ha(a re+erencia a la relaci$n en!re un e+e de pro.ec!o con )arios pro.ec!os. 's!a e!i/ue!a depender* del !ipo de colecci$n /ue se ha.a implemen!ado. : con!inuaci$n el mapeo para la clase <efe.royecto /ue implemen!a una colecci$n de !ipo 6Set. <class name=PSefe(ro ectoP table=PtblSefe(ro ectoP> <id name==dSefe(ro ecto> <column name==dSefe(ro ecto sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <set name=P(ro ectosP> <+e column=PidSefe(ro ectoP 1> <one-to-man class=P(ro ectoP 1> <1set> <1class> Bo /ue se indica en la e!i/ue!a =set> es el nombre de la propiedad de la colecci$n de pro.ec!os. Bue(o se indica /ue la relaci$n en!re pro.ec!os . e+e de pro.ec!o se har* median!e la columna id<efe.royecto de la !abla asociada a la clase .royecto. 2on es!a con+i(uraci$n es posible crear pro.ec!os . asociarlos a un e+e de pro.ec!o en par!icular. Gn e emplo de c$mo reali"ar es!a acci$n es el si(uien!eM Sefe(ro ecto R! = ne@ Sefe(ro ecto:;? S!.(ro ectos = ne@ =esi."ollections.%ashedSet:;? (ro ecto !1 = ne@ (ro !1.4escri!cion = B!ro (ro ecto !H = ne@ (ro !H.4escri!cion = B!ro (ro ecto !1 = ne@ (ro !1.4escri!cion = B!ro !1.Save:;? !H.Save:;? !/.Save:;? R!.(ro ectos.Add:!1;? R!.(ro ectos.Add:!H;? R!.(ro ectos.Add:!/;? R!.Save:;? ecto:;? ecto 1? ecto:;? ecto H? ecto:;? ecto /?

#n!roducci$n a %&iberna!e

22

1J Se !uede im!lementar Que en el mVtodo Save de Sefe(ro ecto se guarden !rimero los !ro ectos luego el obReto Sefe(ro ecto. J1 ')en!ualmen!e- la clase .royecto puede !ener el o!ro e5!remo de la relaci$n uno0 a0muc/os- es decir !endr* un elemen!o de relaci$n muchosFaFuno ;como el )is!o en a(re(aci$n<. 's!o implica a(re(ar una propiedad de !ipo <efe.royecto en la clase .royecto . lue(o de+inir el si(uien!e archi)o de mapeo de la clase .royecto. <class name=P(ro ectoP table=Ptbl(ro ectoP> <id name==d(ro ecto> <column name==d(ro ecto sQl-t !e=char:/H; not-null=true1> <generator class=uuid.hex1> <1id> <!ro!ert name=4escri!cion column=descri!cion1> <man -to-one name=R!=d class=Sefe(ro ecto column==dSefe(ro ecto1> <1class> 'n es!e e emplo- la clase .royecto !iene un a!ribu!o llamado ?p6d de !ipo <efe.royecto- el cual ser* una re+erencia al con!enido de la columna 6d<efe.royecto de la !abla asociada a la clase <efe.royecto.
=set>. =bag>. 2ada una de es!as e!i/ue!as es!* orien!ada a sopor!ar un !ipo de colecci$n en par!icular. : con!inuaci$n se lis!an las principales carac!er3s!icas de cada uno de es!os elemen!osC =list>- =map>

Bas colecciones de ob e!os pueden ser mapeadas u!ili"ando las e!i/ue!as

<set>: 2olecci$n desordenada sin duplicados. 2ompa!ible con la in!er+a" 6esi.4ollections.6Set. <list>: 2olecci$n ordenada- re/uiere una columna 3ndice. 2ompa!ible con la in!er+a" System.4ollections.6;ist. <map>: 2olecci$n /ue almacena pares de elemen!os. 2ompa!ible con la in!er+a" System.4ollections.6'ictionary. <bag>: 2olecci$n desordenada /ue permi!e elemen!os duplicados. 8ir)e para represen!ar lis!as no ordenadas. 9ambi4n es posible u!ili"ar las e!i/ue!as =array> . =primiti)e0array> pero no se ha encon!rando in+ormaci$n sobre es!as e!i/ue!as. Gna propiedad impor!an!e del mapeo de colecciones de ob e!os es conocida como iniciali1aci5n pere1osa o carga pere1osa *la1y loading: la1y initiali1ation+ . 's!a es!ra!e(ia indica /ue si un ob e!o $ !iene una colecci$n de ob e!os %- en!onces al recuperar K desde la base de da!os- s$lo se recuperar*n las propiedades a!$micas de $ ;!ipo 8!rin(- #n!- 2har- 0oolean- e!c< pero no las colecciones de ob e!os % asociados a $ sino has!a /ue realmen!e se /uiera u!ili"ar la colecci$n de ob e!os %. 'n el caso de <efe.royecto s$lo se recupera el iden!i+icador del e+e de pro.ec!o- . lue(o- si en al(Dn momen!o se re/uiere recorrer la colecci$n de pro.ec!os car(o de es!e e+e de pro.ec!os$lo en!onces se recuperar* la colecci$n de pro.ec!os desde la base de da!os. 's!a

#n!roducci$n a %&iberna!e

23

carac!er3s!ica se puede de+inir en el archi)o de mapeo indicando elemen!os =set>- =list>- =map> o =bag>.

lazy=true

en los

4.5 Mapeo de relaciones muchos a muchos.


'l mapeo muchos a muchos consis!e en /ue dadas dos clases- A . @- en!onces A !iene una colecci$n de ob e!os de !ipo @ . a la )e"- la clase @ !iene una colecci$n de ob e!os de !ipo A. 's!a relaci$n en!re A . @ se puede lle)ar al modelo de 0D u!ili"ando una !abla in!ermedia /ue relacione los c$di(os de los elemen!os de A con los elemen!os de @. 's!a !abla in!ermedia s$lo es!ar* cons!i!uida por cla)es +or*neas de las cla)es principales de las !ablas mapeadas de A . @. 'n el si(uien!e caso !enemos /ue un banco !iene una car!era de clien!es- . a su )e"- lo clien!es pueden ser clien!es de )arios bancos. 'l modelo de es!e caso se )er3a al(o como si(ueC

's!a relaci$n muchos a muchos debe ser represen!ada en un modelo relacional a=adiendo una !ercera !abla /ue ha(a de N,@ en!re @anco . 4liente- es decir es!a !ercera !abla relacionar* a los clien!es con los bancos- !eniendo plena liber!ad de relacionar cual/uier clien!e con cual/uier banco ;claro sin permi!ir repe!ici$n<.

9eniendo es!e modelo de clases . su respec!i)o modelo relacional podemos reali"ar el mapeo OR cosa de poder persis!ir nues!ras clases. <class name=Canco table=Canco> <id name==4> <generator class=identit 1> <1id> <set name="lientes laI =true

#n!roducci$n a %&iberna!e

24

table=Canco6"liente> <+e column=Canco=41> <man -to-man class="liente column="liente=41> <1set> <1class> <class name="liente table="liente> <id name==4> <generator class=identit 1> <1id> <!ro!ert name=#ombre column=#ombre 1> <!ro!ert name=A!ellido column=A!ellido 1> <1class> 1ara e5plicar c$mo se reali"a el mapeo muchosFaFmuchos )eremos en de!alle la e!i/ue!a de la colecci$nC <set name="lientes laI =true table=Canco6"liente> <+e column=Canco=41> <man -to-man class="liente column="liente=41> <1set> Ba relaci$n en!re @anco . 4liente se reali"a buscando una ins!ancia en la !abla @anco84liente /ue con!en(a en la columna @anco6' el iden!i+icador del banco . en la columna 4liente6' el iden!i+icador asociado a la clase 4liente. Bas colecciones sopor!adas por las relaciones muc/os0a0muc/os son las mismas /ue para el caso de uno0a0muc/os . las re(las de de+inici$n son las mismas ;a!ribu!os de clase de+inidos como de !ipo de la in!er+a" correspondien!e ;6Set- 6;ist- e!c.<.

#n!roducci$n a %&iberna!e

25

(.- )anipulacin de datos persistentes.


'n la secci$n an!erior- )imos e emplos b*sicos de c$mo crear ob e!os persis!en!es . c$mo re(is!rar es!a persis!encia en la base de da!os. :hora )eremos c$mo recuperar ob e!os de la base de da!os para poder modi+icar sus es!ados . (uardar es!os nue)os es!ados en la base de da!os.

5.1 Recuperando un objeto de la base de datos.


&a. dos modos de recuperar ob e!os desde la base de da!os- ambos basados en el #d del ob e!o ;cla)e primaria de la !abla asociada<. 'l primero de ellos se in)oca cuando creamos el ob e!o ;en es!e caso tom<. 'l m4!odo ;oad re!orna un ob e!o- por lo /ue es necesario hacer el cast al ob e!o re/uerido. 2omo par*me!ros debemos indicar el !ipo del ob e!o re/uerido . el id /ue es!amos buscando. "at tom = :"at; session.Moad:t !eof:"at;& idCuscado;? O!ra opci$n es crear el ob e!o . lue(o llamar al m4!odo Boad- ahora como primer par*me!ro indicamos el ob e!o donde ser* almacenado el resul!ado de la car(a . como se(undo par*me!ro el iden!i+icador del ob e!o a recuperar. "at tom = ne@ "at:;? Session.Moad:tom& idCuscado;? 'l m4!odo ;oad lan"a una NHibernate.UnresolvableObjectException en caso de no e5is!ir el ob e!o asociado al iden!i+icador dado como par*me!ro. Gna al!erna!i)a al uso del m4!odo ;oad es u!ili"ar el m4!odo Aet de la clase session. 's!e m4!odo de)uel)e el ob e!o indicado . en caso de no encon!rarlo re!orna null- por lo /ue es m*s indicado para comprobar la e5is!encia de un ob e!o. 9ambi4n !iene la opci$n de in)ocarlo de!erminando el blo/ueo /ue se /uiera ob!ener para el ob e!o recuperado. "at tom = :"at; session.Tet:t !eof:"at;& idCuscado;? "at !er+ins = :"at; session.Tet:t !eof:"at;& idH& bloqueo;? Gna opci$n in!eresan!e es re+rescar el con!enido de un ob e!o ;en caso /ue ha.a sido ac!uali"ado desde o!ro sis!ema o sesi$n<. 'l m4!odo a u!ili"ar es 7efres/- al cual se le debe indicar el ob e!o a re+rescar. session.Fefresh:cat;?

#n!roducci$n a %&iberna!e

26

5.2 Realizando consultas simples.


's comDn /ue no cono"camos con an!erioridad el iden!i+icador del o los ob e!os /ue /ueramos recuperar de la base de da!os. Fren!e a es!as si!uaciones los m4!odos ;oad . Aet no son D!iles . es necesario u!ili"ar o!ra es!ra!e(ia. 8e pueden recuperar ob e!os desde la base de da!os u!ili"ando una consul!a en len(ua e &@B ;&iberna!e @uero Ban(ua(e<- el cual se )er* en pro+undidad m*s adelan!e. : con!inuaci$n se presen!an al(unos e emplos de consul!as a la base de da!os =Luer Q1 = session.createLuer :Bfrom "at as cat;? =Mist lista = Q1.Mist:;? =Luer QH = session.createLuer :Bfrom "at as cat W B@here cat.#ombre=GnombreTato;? QH.Set(arameter:BnombreTato&valor;? =Mist listaH = QH.Mist:;? "at !rimerTato = QH.Mist:;X0Y 1odemos reali"ar consul!as /ue ob!en(an m*s de un campo como resul!ado de la si(uien!e maneraC =#umerable resultado = session.Nnumerable: Bselect mc.b& mc.c& count:mc; from mi"lass mc W Bgrou! b mc.a ;? foreach : obRectXY filaActual in resultado ;< 1J ti!o1 ti!oH son los ti!os de las columnas 1 de la consulta Que hemos realiIado J1 ti!o1 col1 = :ti!o1; filaActualX0Y? ti!oH colH = :ti!oH; filaActualX1Y? int total = :int; filaActualXHY? D H

#n!roducci$n a %&iberna!e

27

También podría gustarte