Sie sind auf Seite 1von 20

Persistencia de un Modelo de Objetos

persistencia: capacidad de almacenar y


recuperar el estado de los objetos, de forma que sobrevivan a los procesos que los manipulan

UTN Jorge Ercoli (Docente TSSI)

Formas de persistir un objeto


Serializacin
proceso de convertir el estado de un objeto a un formato que se pueda almacenar o transportar.

Tipos: Binaria XML Soap (en .Net)

BD

Orientadas a Objetos
BDOO

Permite persistir las clases tal como fueron diseadas


BDR

BD

Relacionales

Tablas y relaciones La opcin ms usada por : std (SQL), X costo y robustez

Arquitectura basada en Capas


Presentacin

Interaccin entre usuario y aplicacin

Lgica

del dominio

Objetos y reglas de negocio Lgica de los procesos (basado en CU)

Persistencia

Servicios para comunicar la capa lgica con el almacenamiento (BD) Capa de acceso a datos (DAO DAC) (Ejs.: ADO.Net Hibernate)

Modelado de capa lgica

Transaction Script Un procedimiento X accin del usuario (1 controladora del sistema 1 X cada CU) Dificil de aplicar si el dominio es complejo Se ve a la aplicacin como una serie de transacciones Domain Model Diseo OO de los componentes del sistema se incorporan conceptos como herencia y patrones de diseo Problema: GAP entre el modelo de objetos y la BDR Aplicacin vista como un set de objetos interrelacionados

Resumiendo : En TS no hacemos un diseo OO, simplemente escribimos mtodos por c/solicitud de la IU y los encapsulamos en 1 + clases. En DM diseamos una aplicacin OO donde podemos aplicar todo tipo de asociaciones entre objetos (entre ellas la herencia).

Arquitectura de la capa de persistencia

Table Gateway

para cada tabla tenemos asociada una implementacin de tipo CRUD (Create-Retrieve-Update-Delete) La estructura de datos que es utilizada gralmente. para comunicarse tanto con la base de datos como con la capa de lgica, es de tipo Record Set (DataSet en ADO.Net) ResultSet (JDBC)

Row Gateway

Similar al anterior, aunque se trabaja a nivel de filas de la tabla, por lo que las operaciones CRUD tienen asociadas implcitamente la clave de la fila Las operaciones de bsqueda pueden ser servicios estticos de la clase o pertenecer a una nueva clase

Capa de persistencia, continuacin

Active Record

Generalmente se comenzo con Row Gateway y se le adicion lgica del dominio La bsqueda se hace en otra clase

Data Mapper

Abstrae totalmente la lgica de la BD transferir informacin entre la base de datos y los objetos de la capa de lgica sin que estos tomen conocimiento

Integracin de tcnicas de capa lgica con persistencia

T. Script

Row gateway Table gateway Active record Data mapper

Domain Model

Domain Model con Data Mapper = ORM (object relational mapping)


Un ejemplo de ORM: Nhibernate, versin del Hibernate para .NET

Librera de persistencia de objetos para BD relacionales Arquitectura :

NHibernate

Un ORM como Hibernate implica:


No trabajar con filas de tablas (DataRows RecordSet ResultSet) Trabajar con las clases diseadas en su modelo del dominio Cdigo OO limpio, que permite trabajar con herencia y polimorfismo en nuestras clases de negocio Permite elegir la BD relacional con la que querramos interactuar (SqlServer-PostGre-MySql-DB2, Oracle,...) Genera automticamente el cd. SQL usando un mapeo objetorelacional, el cual se especifica en un documento XML Permite crear, modificar, recuperar y borrar objetos persistentes. Al recuperarlos nos permite navegar por las asociaciones entre objs. y luego actualizarlos al finalizar una transaccin.

Ejemplo: .......
Venta v=sesion.Load(typeof(Venta), idventa); v.Lineas.Add(nuevaLinea); v.Cliente.Saldo=v.Cliente.Saldo + nuevaLinea.Total; Transaccion.Commit();

Nhibernate El proceso de desarrollo


1. Crear la clase que necesita ser persistida

2. Crear la tabla para persistir la clase


3. Crear un archivo de mapeo para que NHibernate sepa como persistir las propiedades de la clase 4. Crear un archivo de configuracin para que NHibernate sepa como conectarse a su BD.

5. Usar el API del NHibernate

Creamos las clases y las tablas (1 y 2)

Hacemos el mapping (3)


<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" default-access="property"> <class name="TPVBO.Venta, TPVBO" table="Venta" > <id name="VentaID" column="idVenta" unsaved-value="0"> <generator class="identity" /> </id> <property name="Fecha" type = "DateTime" /> Venta.hbm.xml <property name="Numero" type = "Int32" />
<bag name="LineaVenta" cascade="all"> <key column="venta"/> <one-to-many class="TPVBO.LineaVenta, TPVBO"/> </bag> </class> </hibernate-mapping> ................... <class name="TPVBO.LineaVenta, TPVBO" table="lineaventa" > <id name="LineaVentaID" column=idLineaVta" unsaved-value="0"> <generator class="identity" /> </id> <property name="Cantidad" type = "Int32" /> LineaVenta.

hbm.xml
</class> </hibernate-mapping>

<many-to-one name=Producto" class="TPVBO.Producto, TPVBO" column="producto" />

Creamos el archivo de configuracin (4)


<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </configSections> <nhibernate> <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /> <add key="hibernate.dialect" value="NHibernate.Dialect.MySQLDialect" /> <add key="hibernate.connection.driver_class" value="NHibernate.Driver.MySqlDataDriver" /> <add key="hibernate.connection.connection_string" value="Server=localhost;Database=TpvHibernate;User ID=jorge;Password=jorge" /> </nhibernate> </configuration>

Generalmente en el app.config de la aplicacin

Usamos la API del Nhibernate (5)


1. 2. Agregamos una referencia a NHibernate.dll (para usarlo en nuestra aplicacin) Creamos un objeto de Configuracin

Configuration cfg = new Configuration();


3. Le decimos al Configuration sobre los tipos de objetos que vamos a persistir

cfg.AddAssembly(TPVBO");
4.

// En TPVBO.dll estn mis class con mis class.hbm.xml....

Creamos una Fabrica de sesiones (1 X BD) y luego le pedimos una Session y comenzamos una transaccin.

ISessionFactory factory = cfg.BuildSessionFactory(); ISession session = factory.OpenSession();

ITransaction transaction = session.BeginTransaction();


5. Trabajamos con nuestros objetos

Producto p=new Producto(); p.Codigo=CA123; p.Descripcion=Camisa CA; p.Precio=59.90;

session.Save(p);
6. Grabamos la transaccin en la BD y cerramos la sesin.

transaction.Commit(); session.Close();

La Session en NHibernate:

La session

Es el punto de contacto principal para trabajar con Nhibernate


Nuestros objetos se asocian a ella para poder realizar operaciones de persistencia (Save, Update, Delete, Load Get)

Con una session abierta ISession session = factory.OpenSession();


1. Grabar actualizar p.precio = 62.45; session.SaveOrUpdate(p); // har un Insert si el ID=0, sino un Update con el ID corresp. al objeto session.Flush(); // permite bajar todos los cambios a la BD (sin necesidad de tener una transaccin) 2. Leer uno o mas objetos Producto p = session.Load( typeof(Producto),m_ID); // Busca el objeto Producto con ese m_ID // Usamos el HQL, similar a SQL pero nombrando los atributos de nuestra clase, NO campos de Tabla! ArrayList misProd = session.Find( from Producto p where p.Precio > 50); 3. Borrar session.Delete(p); // borramos nuestro objeto p de tipo Producto session.Flush();

Las asociaciones entre objetos

Definen las relaciones entre las clases Se definen en el archivo de mapeo (clase.hbm.xml) NHibernate usa los mapeos de asociaciones para grabar y recuperar automaticamente los objetos relacionados :

<one-to-one> Una Venta tiene un Pedido <one-to-many> Una Venta tiene muchas lineaVenta <many-to-one> Una lineaVenta tiene un Producto (muchas lineaVenta, un Producto) <many-to-many> Un Empleado tiene muchas Tareas, y una Tarea tiene muchos Empleados

Mapeando herencia
<class name="TPVBO.Producto, TPVBO" table="Producto" > <id name="ProductoID" column="productoID" unsaved-value="0"> <generator class="identity" /> </id> <property name="Codigo" type = "String(15)" /> <property name="Descrip" type = "String(40)" /> <property name="Precio" type = "Decimal(10,2)" /> <joined-subclass name="TPVBO.Articulo, TPVBO" table="Articulo"> <key column="ProductoID"/> <property name="Costo" type = "Decimal(10,2)" />

<property name="Stock" type = "Int32" />


</joined-subclass> <joined-subclass name="TPVBO.Promocion,TPVBO" table=Promocion"> <key column="ProductoID"/> <property name="Validez" type = "DateTime" /> <bag name="Articulos" cascade="all"> <key column="promocion"/> <one-to-many class="TPVBO.Articulo, TPVBO"/> </bag> </joined-subclass> </class>

Manejo de colecciones
// Creo una Venta En el mapping de venta dice : <bag name="LineaVenta" cascade="all"> Venta v=new Venta(); v.Fecha=hoy; v.Numero=22; // Creo 2 lineas de venta LineaVenta l1=new LineaVenta(); l1.Cantidad=10; l1.Producto=session.Load(typeof(Producto),155); LineaVenta l2=new LineaVenta(); l2.Cantidad=5; l2.Producto=session.Load(typeof(Producto),189); // agrego a la coleccin de lineas de venta de v, las 2 lineas creadas

v.lineas.Add(l1); v.lineas.Add(l2);
// grabo la venta a la session con sus 2 lineas (por tener el cascade=all): En la BD se inserta una fila en Venta y 2 en LineaVenta session.Save(v); session.Flush();

Trabajando con transacciones (la forma usual...)


try { session = factory.OpenSession(); transaction = session.BeginTransaction(); session.SaveOrUpdate(miObjetoNegocio); transaction.Commit(); }

catch (Exception ex) {


transaction.Rollback(); } finally { session.Close(); }

Y el manejo de la concurrencia?
Se puede agregar un campo timeStamp (dateTime) en cada tabla de la BD y un atributo en la clase. Luego en el mapeo (XML): <version name="Version" column="version" type = "DateTime" /> try { this.sesion.SaveOrUpdate(this.p); tx.Commit(); } catch (NHibernate.StaleObjectStateException ex) { tx.Rollback(); // Otro usr. realizo cambios, pregunto si quiere reLeer DialogResult resp; resp=MessageBox.Show(Este registro ha variado desde la ltima vez que se recuper, desea ver su estado actual?", "Aviso", MessageBoxButtons.YesNo); if(resp == DialogResult.Yes) this.recuperaDatos(this.p); } finally{this.sesion.Close();}

Das könnte Ihnen auch gefallen