persistencia de un modelo de objetos

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)

Upload: jorge-ercoli

Post on 05-Jul-2015

18.379 views

Category:

Technology


2 download

DESCRIPTION

Persistir un modelo de objetos mediante un ORM como NHibernate, arquitectura y ejemplos del mismo.

TRANSCRIPT

Page 1: Persistencia de un modelo de objetos

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)

Page 2: Persistencia de un modelo de objetos

Formas de persistir un objetoSerialización 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 ObjetosPermite persistir las clases tal como fueron diseñadas

BDR BDOO

BD RelacionalesTablas y relaciones – La opción más usada por : std (SQL),X costo y robustez

Page 3: Persistencia de un modelo de objetos

Arquitectura basada en Capas

Presentación Interacción entre usuario y

aplicación

Lógica del dominio Objetos y reglas de negocio Lógica de los procesos (basado en CU)

Persistencia Servicios para comunicar la capa

lógica con el almacenamiento (BD) Capa de acceso a datos (DAO ó DAC) (Ejs.: ADO.Net – Hibernate)

Page 4: Persistencia de un modelo de objetos

Modelado de capa lógica Transaction Script

Un procedimiento X acción del usuario (1 controladora del sistema ó 1 X cada CU)

Dificil de aplicar si el dominio es complejo Se ve a la aplicación como una serie de transacciones

Domain Model Diseño OO de los componentes del sistema se incorporan conceptos como herencia y patrones de diseño Problema: GAP entre el modelo de objetos y la BDR Aplicación vista como un set de objetos interrelacionados

Resumiendo : En TS no hacemos un diseño OO, simplemente escribimos métodos por c/solicitud de la IU y los encapsulamos en 1 ó + clases. En DM diseñamos una aplicación OO donde podemos aplicar todo tipo de asociaciones entre objetos (entre ellas la herencia).

Page 5: Persistencia de un modelo de objetos

Arquitectura de la capa de persistencia

Table Gateway para cada tabla tenemos asociada una implementación 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 lógica, 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 implícitamente la clave de la fila Las operaciones de búsqueda pueden ser servicios estáticos de la clase o

pertenecer a una nueva clase

Page 6: Persistencia de un modelo de objetos

Capa de persistencia, continuación

Active Record Generalmente se comenzo con Row Gateway y se le adicionó lógica del

dominio La búsqueda se hace en otra clase

Data Mapper Abstrae totalmente la lógica de la BD transferir información entre la base de datos y los objetos de la capa de

lógica sin que estos tomen conocimiento

Page 7: Persistencia de un modelo de objetos

Integración de técnicas de capa lógica con persistencia

T. Script

Domain Model

Row gateway

Table gateway

Active record

Data mapper

Page 8: Persistencia de un modelo de objetos

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

Librería de persistencia de objetos para BD relacionales Arquitectura :

Un ejemplo de ORM: “Nhibernate”, versión del Hibernate para .NETN

Hibernate

Page 9: Persistencia de un modelo de objetos

Un ORM como Hibernate implica: No trabajar con filas de tablas (DataRows ó RecordSet ó ResultSet) Trabajar con las clases diseñadas en su modelo del dominio Código 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 automáticamente el cód. SQL usando un mapeo objeto-relacional, 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 transacción.

Ejemplo: .......

Venta v=sesion.Load(typeof(Venta), idventa);

v.Lineas.Add(nuevaLinea);

v.Cliente.Saldo=v.Cliente.Saldo + nuevaLinea.Total;

Transaccion.Commit();

Page 10: Persistencia de un modelo de objetos

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 configuración para que NHibernate sepa como conectarse a su BD.

5. Usar el API del NHibernate

Page 11: Persistencia de un modelo de objetos

Creamos las clases y las tablas (1 y 2)

Page 12: Persistencia de un modelo de objetos

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" /><property name="Numero" type = "Int32" />

<bag name="LineaVenta" cascade="all"><key column="venta"/><one-to-many class="TPVBO.LineaVenta, TPVBO"/>

</bag></class>

</hibernate-mapping>

Venta.hbm.xml

...................<class name="TPVBO.LineaVenta, TPVBO" table="lineaventa" >

<id name="LineaVentaID" column=“idLineaVta" unsaved-value="0"><generator class="identity" />

</id><property name="Cantidad" type = "Int32" />

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

</class></hibernate-mapping>

LineaVenta.

hbm.xml

Page 13: Persistencia de un modelo de objetos

Creamos el archivo de configuración (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

aplicación

Page 14: Persistencia de un modelo de objetos

Usamos la API del Nhibernate (5)1. Agregamos una referencia a NHibernate.dll (para usarlo en nuestra aplicación)

2. Creamos un objeto de Configuración

Configuration cfg = new Configuration();

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

cfg.AddAssembly(“TPVBO"); // En TPVBO.dll están mis class con mis class.hbm.xml....

4. Creamos una Fabrica de sesiones (1 X BD) y luego le pedimos una Session y comenzamos una transacción.

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 transacción en la BD y cerramos la sesión.

transaction.Commit();

session.Close();

Page 15: Persistencia de un modelo de objetos

La Session en NHibernate:

• 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)

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 transacción)

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();

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

La session

Page 16: Persistencia de un modelo de objetos

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

Page 17: Persistencia de un modelo de objetos

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>

Page 18: Persistencia de un modelo de objetos

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 colección 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();

Page 19: Persistencia de un modelo de objetos

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();

}

Page 20: Persistencia de un modelo de objetos

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();}