Persistencia de un Modelo de Objetos “ persistencia : capacidad de almacenar y recuperar el estado de los objetos, de form...
Formas de persistir un objeto <ul><li>Serialización </li></ul><ul><li>proceso de convertir el estado de un objeto a un for...
Arquitectura basada en Capas <ul><li>Presentación </li></ul><ul><li>Interacción entre usuario y  </li></ul><ul><li>aplicac...
Modelado de capa lógica <ul><li>Transaction Script </li></ul><ul><ul><li>Un procedimiento X acción del usuario (1 controla...
Arquitectura de la capa de persistencia <ul><li>Table Gateway </li></ul><ul><ul><li>para cada tabla tenemos asociada una i...
Capa de persistencia, continuación <ul><li>Active Record  </li></ul><ul><ul><li>Generalmente se comenzo con Row Gateway y ...
Integración de técnicas de capa lógica con persistencia <ul><li>T. Script </li></ul><ul><li>Domain Model </li></ul><ul><li...
Domain Model con Data Mapper =  ORM  ( object relational mapping ) <ul><li>Librería de persistencia de objetos para BD rel...
Un ORM como Hibernate implica: <ul><li>No trabajar con filas de tablas ( DataRows ó RecordSet ó ResultSet ) </li></ul><ul>...
Nhibernate – El proceso de desarrollo <ul><li>1. Crear la clase que necesita ser persistida  </li></ul><ul><li>2. Crear la...
Creamos las clases y las tablas (1 y 2)
Hacemos el mapping   (3) <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>  <hibernate-mapping xmlns=&quot;urn:n...
Creamos el archivo de configuración (4) <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?> <configuration> <confi...
Usamos la API del Nhibernate (5) 1.       Agregamos una referencia a NHibernate.dll (para usarlo en nuestra aplicación)  2...
La session <ul><li>La Session en NHibernate: </li></ul><ul><li>Es el punto de contacto principal para trabajar con Nhibern...
Las asociaciones entre objetos <ul><li>Definen las relaciones entre las clases </li></ul><ul><li>Se definen en el archivo ...
Mapeando herencia <class name=&quot;TPVBO.Producto, TPVBO&quot; table=&quot;Producto&quot; > <id name=&quot;ProductoID&quo...
Manejo de colecciones //  Creo una Venta – En el mapping de venta dice :  <bag name=&quot;LineaVenta&quot; cascade=&quot;a...
Trabajando con transacciones (la forma usual...) try {  session = factory.OpenSession(); transaction = session.BeginTransa...
Y el manejo de la concurrencia? Se puede agregar un campo “timeStamp” (dateTime) en cada tabla de la BD y un atributo en l...
Upcoming SlideShare
Loading in …5
×

Persistencia de un modelo de objetos

18,947 views

Published on

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

Published in: Technology

Persistencia de un modelo de objetos

  1. 1. 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)
  2. 2. Formas de persistir un objeto <ul><li>Serialización </li></ul><ul><li>proceso de convertir el estado de un objeto a un formato que se pueda almacenar o transportar. </li></ul><ul><li>Tipos: Binaria – XML – Soap (en .Net) </li></ul><ul><li>BD Orientadas a Objetos </li></ul><ul><li>Permite persistir las clases tal como fueron diseñadas </li></ul><ul><li>BDR BDOO </li></ul><ul><li>BD Relacionales </li></ul><ul><li>Tablas y relaciones – La opción más usada por : std (SQL), </li></ul><ul><li>X costo y robustez </li></ul>
  3. 3. Arquitectura basada en Capas <ul><li>Presentación </li></ul><ul><li>Interacción entre usuario y </li></ul><ul><li>aplicación </li></ul><ul><li>Lógica del dominio </li></ul><ul><li>Objetos y reglas de negocio </li></ul><ul><li>Lógica de los procesos (basado en CU) </li></ul><ul><li>Persistencia </li></ul><ul><li>Servicios para comunicar la capa </li></ul><ul><li>lógica con el almacenamiento (BD) </li></ul><ul><li>Capa de acceso a datos (DAO ó DAC) </li></ul><ul><li>( Ejs.: ADO.Net – Hibernate ) </li></ul>
  4. 4. Modelado de capa lógica <ul><li>Transaction Script </li></ul><ul><ul><li>Un procedimiento X acción del usuario (1 controladora del sistema ó 1 X cada CU) </li></ul></ul><ul><ul><li>Dificil de aplicar si el dominio es complejo </li></ul></ul><ul><ul><li>Se ve a la aplicación como una serie de transacciones </li></ul></ul><ul><li>Domain Model </li></ul><ul><ul><li>Diseño OO de los componentes del sistema </li></ul></ul><ul><ul><li>se incorporan conceptos como herencia y patrones de diseño </li></ul></ul><ul><ul><li>Problema: GAP entre el modelo de objetos y la BDR </li></ul></ul><ul><ul><li>Aplicación vista como un set de objetos interrelacionados </li></ul></ul>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).
  5. 5. Arquitectura de la capa de persistencia <ul><li>Table Gateway </li></ul><ul><ul><li>para cada tabla tenemos asociada una implementación de tipo CRUD (Create-Retrieve-Update-Delete) </li></ul></ul><ul><ul><li>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) </li></ul></ul><ul><li>Row Gateway </li></ul><ul><ul><li>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 </li></ul></ul><ul><ul><li>Las operaciones de búsqueda pueden ser servicios estáticos de la clase o pertenecer a una nueva clase </li></ul></ul>
  6. 6. Capa de persistencia, continuación <ul><li>Active Record </li></ul><ul><ul><li>Generalmente se comenzo con Row Gateway y se le adicionó lógica del dominio </li></ul></ul><ul><ul><li>La búsqueda se hace en otra clase </li></ul></ul><ul><li>Data Mapper </li></ul><ul><ul><li>Abstrae totalmente la lógica de la BD </li></ul></ul><ul><ul><li>transferir información entre la base de datos y los objetos de la capa de lógica sin que estos tomen conocimiento </li></ul></ul>
  7. 7. Integración de técnicas de capa lógica con persistencia <ul><li>T. Script </li></ul><ul><li>Domain Model </li></ul><ul><li>Row gateway </li></ul><ul><li>Table gateway </li></ul><ul><li>Active record </li></ul><ul><li>Data mapper </li></ul>
  8. 8. Domain Model con Data Mapper = ORM ( object relational mapping ) <ul><li>Librería de persistencia de objetos para BD relacionales </li></ul><ul><li>Arquitectura : </li></ul>Un ejemplo de ORM: “Nhibernate”, versión del Hibernate para .NET NHibernate
  9. 9. Un ORM como Hibernate implica: <ul><li>No trabajar con filas de tablas ( DataRows ó RecordSet ó ResultSet ) </li></ul><ul><li>Trabajar con las clases diseñadas en su modelo del dominio </li></ul><ul><li>Código OO limpio, que permite trabajar con herencia y polimorfismo en nuestras clases de negocio </li></ul><ul><li>Permite elegir la BD relacional con la que querramos interactuar (SqlServer-PostGre-MySql-DB2, Oracle,...) </li></ul><ul><li>Genera automáticamente el cód. SQL usando un mapeo objeto-relacional, el cual se especifica en un documento XML </li></ul><ul><li>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. </li></ul>Ejemplo: ....... Venta v=sesion.Load(typeof(Venta), idventa); v.Lineas.Add(nuevaLinea); v.Cliente.Saldo=v.Cliente.Saldo + nuevaLinea.Total; Transaccion.Commit();
  10. 10. Nhibernate – El proceso de desarrollo <ul><li>1. Crear la clase que necesita ser persistida </li></ul><ul><li>2. Crear la tabla para persistir la clase </li></ul><ul><li>3. Crear un archivo de mapeo para que NHibernate sepa como persistir las propiedades de la clase </li></ul><ul><li>4. Crear un archivo de configuración para que NHibernate sepa como conectarse a su BD. </li></ul><ul><li>5. Usar el API del NHibernate </li></ul>
  11. 11. Creamos las clases y las tablas (1 y 2)
  12. 12. Hacemos el mapping (3) <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?> <hibernate-mapping xmlns=&quot;urn:nhibernate-mapping-2.0&quot; default-access=&quot;property&quot;> <class name=&quot;TPVBO.Venta, TPVBO&quot; table=&quot;Venta&quot; > <id name=&quot;VentaID&quot; column=&quot;idVenta&quot; unsaved-value=&quot;0&quot;> <generator class=&quot;identity&quot; /> </id> <property name=&quot;Fecha&quot; type = &quot;DateTime&quot; /> <property name=&quot;Numero&quot; type = &quot;Int32&quot; /> <bag name=&quot;LineaVenta&quot; cascade=&quot;all&quot;> <key column=&quot;venta&quot;/> <one-to-many class=&quot;TPVBO.LineaVenta, TPVBO&quot;/> </bag> </class> </hibernate-mapping> Venta.hbm.xml ................... <class name=&quot;TPVBO.LineaVenta, TPVBO&quot; table=&quot;lineaventa&quot; > <id name=&quot;LineaVentaID&quot; column=“idLineaVta&quot; unsaved-value=&quot;0&quot;> <generator class=&quot;identity&quot; /> </id> <property name=&quot;Cantidad&quot; type = &quot;Int32&quot; /> <many-to-one name=“Producto&quot; class=&quot;TPVBO.Producto, TPVBO&quot; column=&quot;producto&quot; /> </class> </hibernate-mapping> LineaVenta. hbm.xml
  13. 13. Creamos el archivo de configuración (4) <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?> <configuration> <configSections> <section name=&quot;nhibernate&quot; type=&quot;System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089&quot; /> </configSections> <nhibernate> <add key=&quot;hibernate.connection.provider&quot; value=&quot;NHibernate.Connection.DriverConnectionProvider&quot; /> <add key=&quot;hibernate.dialect&quot; value=&quot;NHibernate.Dialect.MySQLDialect&quot; /> <add key=&quot;hibernate.connection.driver_class&quot; value=&quot;NHibernate.Driver.MySqlDataDriver&quot; /> <add key=&quot;hibernate.connection.connection_string&quot; value=&quot;Server=localhost;Database=TpvHibernate;User ID=jorge;Password=jorge&quot; /> </nhibernate> </configuration> Generalmente en el app.config de la aplicación
  14. 14. 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&quot;); // 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();
  15. 15. La session <ul><li>La Session en NHibernate: </li></ul><ul><li>Es el punto de contacto principal para trabajar con Nhibernate </li></ul><ul><li>Nuestros objetos se asocian a ella para poder realizar operaciones de persistencia (Save, Update, Delete, Load ó Get) </li></ul><ul><li>Grabar ó actualizar </li></ul><ul><ul><li>p.precio = 62.45; </li></ul></ul><ul><ul><li>session.SaveOrUpdate(p); // hará un Insert si el ID=0, sino un Update con el ID corresp. al objeto </li></ul></ul><ul><ul><li>session.Flush(); // permite bajar todos los cambios a la BD (sin necesidad de tener una transacción) </li></ul></ul><ul><li>Leer uno o mas objetos </li></ul><ul><ul><li>Producto p = session.Load( typeof(Producto),m_ID); // Busca el objeto Producto con ese m_ID </li></ul></ul><ul><ul><li>// Usamos el HQL, similar a SQL pero nombrando los atributos de nuestra clase, NO campos de Tabla! </li></ul></ul><ul><ul><li>ArrayList misProd = session.Find( “from Producto p where p.Precio > 50”); </li></ul></ul><ul><li>Borrar </li></ul><ul><ul><li>session.Delete(p); // borramos nuestro objeto p de tipo Producto </li></ul></ul><ul><ul><li>session.Flush(); </li></ul></ul>Con una session abierta  ISession session = factory.OpenSession();
  16. 16. Las asociaciones entre objetos <ul><li>Definen las relaciones entre las clases </li></ul><ul><li>Se definen en el archivo de mapeo (clase.hbm.xml) </li></ul><ul><li>NHibernate usa los mapeos de asociaciones para grabar y recuperar automaticamente los objetos relacionados : </li></ul><ul><ul><li><one-to-one> – Una Venta tiene un Pedido </li></ul></ul><ul><ul><li><one-to-many> – Una Venta tiene muchas lineaVenta </li></ul></ul><ul><ul><li><many-to-one> – Una lineaVenta tiene un Producto (muchas lineaVenta, un Producto) </li></ul></ul><ul><ul><li><many-to-many> – Un Empleado tiene muchas Tareas, y una Tarea tiene muchos Empleados </li></ul></ul>
  17. 17. Mapeando herencia <class name=&quot;TPVBO.Producto, TPVBO&quot; table=&quot;Producto&quot; > <id name=&quot;ProductoID&quot; column=&quot;productoID&quot; unsaved-value=&quot;0&quot;> <generator class=&quot;identity&quot; /> </id> <property name=&quot;Codigo&quot; type = &quot;String(15)&quot; /> <property name=&quot;Descrip&quot; type = &quot;String(40)&quot; /> <property name=&quot;Precio&quot; type = &quot;Decimal(10,2)&quot; /> <joined-subclass name=&quot;TPVBO.Articulo, TPVBO&quot; table=&quot;Articulo&quot;> <key column=&quot;ProductoID&quot;/> <property name=&quot;Costo&quot; type = &quot;Decimal(10,2)&quot; /> <property name=&quot;Stock&quot; type = &quot;Int32&quot; /> </joined-subclass> <joined-subclass name=&quot;TPVBO.Promocion,TPVBO&quot; table=“Promocion&quot;> <key column=&quot;ProductoID&quot;/> <property name=&quot;Validez&quot; type = &quot;DateTime&quot; /> <bag name=&quot;Articulos&quot; cascade=&quot;all&quot;> <key column=&quot;promocion&quot;/> <one-to-many class=&quot;TPVBO.Articulo, TPVBO&quot;/> </bag> </joined-subclass> </class>
  18. 18. Manejo de colecciones // Creo una Venta – En el mapping de venta dice : <bag name=&quot;LineaVenta&quot; cascade=&quot;all&quot;> 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();
  19. 19. 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(); }
  20. 20. 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=&quot;Version&quot; column=&quot;version&quot; type = &quot;DateTime&quot; /> 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?&quot;, &quot;Aviso&quot;, MessageBoxButtons.YesNo); if(resp == DialogResult.Yes) this.recuperaDatos(this.p); } finally{this.sesion.Close();}

×