Investigación de patrones de base de datos

26
Patrones auxiliares de acceso a datos. a) Singleton El patrón Singleton se implementa mediante una clase con un constructor privado. Existirá un método que creará una instancia del objeto llamando al constructor sólo si todavía no existe ninguna. Los Singletons normalmente se usan para proporcionar un punto de acceso global para un servicio. De esta forma no hace falta pasar una referencia a este servicio, lo que viene a ser como usar una variable global. Al final lo que ocurre es que las dependencias de diseño permanecen ocultas dentro del código y no son visibles al examinar las interfaces. Hace falta inspeccionar el código para entender qué objetos están usando las clases. Los Singletons permiten limitar la creación de los objetos. Esto es cierto, pero ahora se están mezclando dos responsabilidades diferentes en la misma clase. Una clase no debería preocuparse de si es o no un Singleton, sino que sólo debería preocuparse por sus responsabilidades de negocio. Para limitar la creación de clases se deberían crear factorías u otros objetos que limiten la creación. De esta forma, cada objeto mantendría una responsabilidad mejor definida. Los Singletons promueven el acoplamiento fuerte entre clases. Un acoplamiento flojo entre clases permite sustituir implementaciones alternativas de las clases colaboradoras en las pruebas. Una mejor alternativa es modificar el diseño para pasar referencias a los

description

Patrones de base de datos mas conocidos en el entorno de la promocionan ya que son utilizados para persistir los datos de aplicaciones desarrolladas en los distintos lenguajes como java, c++,etc.

Transcript of Investigación de patrones de base de datos

Page 1: Investigación de patrones de base de datos

Patrones auxiliares de acceso a datos.

a) Singleton

El patrón Singleton se implementa mediante una clase con un constructor privado. Existirá un método que creará una instancia del objeto llamando al constructor sólo si todavía no existe ninguna.

Los Singletons normalmente se usan para proporcionar un punto de acceso global para un servicio. De esta forma no hace falta pasar una referencia a este servicio, lo que viene a ser como usar una variable global. Al final lo que ocurre es que las dependencias de diseño permanecen ocultas dentro del código y no son visibles al examinar las interfaces. Hace falta inspeccionar el código para entender qué objetos están usando las clases.

Los Singletons permiten limitar la creación de los objetos. Esto es cierto, pero ahora se están mezclando dos responsabilidades diferentes en la misma clase. Una clase no debería preocuparse de si es o no un Singleton, sino que sólo debería preocuparse por sus responsabilidades de negocio. Para limitar la creación de clases se deberían crear factorías u otros objetos que limiten la creación. De esta forma, cada objeto mantendría una responsabilidad mejor definida.

Los Singletons promueven el acoplamiento fuerte entre clases. Un acoplamiento flojo entre clases permite sustituir implementaciones alternativas de las clases colaboradoras en las pruebas. Una mejor alternativa es modificar el diseño para pasar referencias a los objetos en las clases y métodos, de forma que se reduzca el acoplamiento.

Page 2: Investigación de patrones de base de datos

Ejemplo:

// Patrones auxiliares de acceso a datos. (Singleton)

public class ConexionBaseDatos{String url;String user;String pass;Conection conexion=null;

private String nombre;

private ConexionBaseDatos{

}

private static conexionBaseDatos getInstance(){return ConexioBdHolder.INSTANCE;

}

private static class ConexioBdHolder {private static final ConexionBaseDatos INSTANCE= new

ConexionBaseDatos();}

public void setConectarBaseDatosMysql(String url,String user, String Pass){

this.url=url;this.user=user;this.pass=pass;

}

public Connection getConectarBaseDatosMysql(){conexion=null;try{

Class.forName("com.mysql.jdbc.Driver");conexion=DriverManager.getConnection(url,user,pass);

}catch(ClassNotFoundException ex){System.out.println("Error no se encontro el Driver")

+ex.getMessage();conexion=null;

}catch(SQLException ex){System.out.println("Error en la con la conexion con la

base de datos")+ex.getMessage();}

}

public void cerrarConexion() throws SQLException{conexion.close;

}

Page 3: Investigación de patrones de base de datos

b) Fachada

Como su propia traducción indica, este patrón actúa de Fachada. Lo que conseguimos es abstraer una capa de otra, de forma que si una capa cambia no hace falta cambiar la otra.

Cuando iniciamos nuestra aplicación se seleccionara la fachada o facade que queremos con la que funciones nuestra aplicación un ejemplo de su utilización es cuando una empresa dispone de MySQL y otra en SQL SERVER no se tiene que cambiar toda la aplicación sino implementar las fachadas distintas y cargar la que se quiere utilizar al principio de la ejecución.

Ejemplo:

// Patrones auxiliares de acceso a datos (Facade).

public class UsersFacade {

public User loginUser(String userName, String password, Integer company_id) throws Exception {

UsersDAO usersDAO = new UsersDAO();User user = usersDAO.getUserByLoginPassword(userName,

password, company_id);return user;}

public User loadUser(int id) throws Exception{UsersDAO usersDAO = new UsersDAO();User user = usersDAO.getUserById(id);return user;}

//Uso de la FachadaUsersFacade uf = new UsersFacade();uf.loadUser(this.view.getSelectedUser().getUserId());

Page 4: Investigación de patrones de base de datos

c) Factory

Este patrón proporciona un objeto factoría abstracta de DAOs (Abstract Factory) que puede construir varios tipos de factorías concretas de DAOs, cada factoría soporta un tipo diferente de implementación del almacenamiento persistente. Una vez que obtenemos la factoría concreta de DAOs para una implementación específica, la utilizamos para producir los DAOs soportados e implementados en esa implementación.

Permite la Transparencia: Los objetos de negocio puede utilizar la fuente de datos sin conocer los detalles específicos de su implementación. El acceso es transparente porque los detalles de la implementación se ocultan dentro del DAO.

Permite una Migración más Fácil: Una capa de DAOs hace más fácil que una aplicación pueda migrar a una implementación de base de datos diferente. Los objetos de negocio no conocen la implementación de datos subyacente, la migración implica cambios sólo en la capa DAO.

Ejemplo:

// Patrones auxiliares de acceso a datos (Factory).public abstract class DAOFactory { public static final int CLOUDSCAPE = 1; public static final int ORACLE = 2; public static final int SYBASE = 3; public abstract CustomerDAO getCustomerDAO(); public abstract AccountDAO getAccountDAO(); public abstract OrderDAO getOrderDAO(); public static DAOFactory getDAOFactory(

int whichFactory) { switch (whichFactory) {

case CLOUDSCAPE: return new CloudscapeDAOFactory();

case ORACLE : return new OracleDAOFactory();

case SYBASE : return new SybaseDAOFactory();

default : return null; } }}//Clase CloudscapeDAOFactorypublic class CloudscapeDAOFactory extends DAOFactory {

public static final String DRIVER="COM.cloudscape.core.RmiJdbcDriver";

public static final String DBURL="jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";

public static Connection createConnection() {}public CustomerDAO getCustomerDAO() {

return new CloudscapeCustomerDAO();

Page 5: Investigación de patrones de base de datos

}public AccountDAO getAccountDAO() {

return new CloudscapeAccountDAO();}

public OrderDAO getOrderDAO() {return new CloudscapeOrderDAO();}

}

Patrones de acceso a datos

a) Active Record

El patrón Active Record es un patrón de arquitectura de software que almacena los datos en base de datos relacionales. La interface del objeto que conforma a este patrón, deberá incluir funciones Insert, Update y Delete y adempas, propiedades que corresponde directamente a las columnas que se encuentran en la tabla de la base de datos. Este patrón es comúnmente usado por herramientas para persistis objetos y además en los Object-Relational Mapping (ORM).

Ejemplo:

El lenguaje Java implementa este patrón a través de la librería ActiveJDBC, el cual es inspirado en Ruby on rails Active Record. ActiveJDBC es ligero, rápido y pequeño y no requiere ninguna configuración.

package activejdbc.examples.simple;

import org.javalite.activejdbc.Model;

public class Employee extends Model { static{ validatePresenceOf("first_name", "last_name"); }}

package activejdbc.examples.simple;

import org.javalite.activejdbc.Base;import org.slf4j.Logger;import org.slf4j.LoggerFactory;

public class SimpleExample { final static Logger logger = LoggerFactory.getLogger(SimpleExample.class); public static void main(String[] args) {

Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "root", "p@ssw0rd");

Page 6: Investigación de patrones de base de datos

createEmployee(); logger.info("=========> Created employee:"); selectEmployee(); updateEmployee(); logger.info("=========> Updated employee:"); selectAllEmployees(); deleteEmployee(); logger.info("=========> Deleted employee:"); selectAllEmployees(); createEmployee(); logger.info("=========> Created employee:"); selectEmployee(); deleteAllEmployees(); logger.info("=========> Deleted all employees:"); selectAllEmployees();

Base.close(); }

private static void createEmployee() { Employee e = new Employee(); e.set("first_name", "John"); e.set("last_name", "Doe"); e.saveIt(); }

private static void selectEmployee() { Employee e = Employee.findFirst("first_name = ?", "John"); logger.info(e.toString()); }

private static void updateEmployee() { Employee e = Employee.findFirst("first_name = ?", "John"); e.set("last_name", "Steinbeck").saveIt(); }

private static void deleteEmployee() { Employee e = Employee.findFirst("first_name = ?", "John"); e.delete(); }

private static void deleteAllEmployees() { Employee.deleteAll(); }

private static void selectAllEmployees() { logger.info("Employees list: " + Employee.findAll()); }}

b) Active Domain Object

Encapsula modelo de datos y acceso a datos detalles dentro de un objeto de dominio correspondiente. En otras palabras, un Active Domain Object abstrae la semántica del almacén de datos subyacente (es decir, SQL Server) y la tecnología de acceso de datos

Page 7: Investigación de patrones de base de datos

subyacente (es decir, ADO.NET) y proporciona una sencilla interfaz de programación para recuperar y operar en los datos.

Ejemplo:

public class Customer{ /* Data members */ private string m_strConnection = ""; // Used by the data accessor object to access database private System.Data.DataRow drCustomer = null;

/* Constructors */ public Customer() { // Acquire the connection string from a connection-string factory-object m_strConnection = ConnectionStringFactory.GetConnectionString(); }

/* Data access methods */ public System.Data.DataRow GetCustomer( int nID ) { // Use data access helper components to retrieve customer data via a stored procedure drCustomer = ... // Return customer information return drCustomer; }

public int CreateCustomer( string strName, string DateTime dtDOB ) { // Use data access helper components to create a new customer entry in the database // and return customer ID }

public void DeleteCustomer( int nCustomerID ) { // Use data access helper components to delete customer from the database }

public void UpdateCustomer( DataRow drCustomer ) { // Use data access helper components to update customer in the database }

/* Properties */

Page 8: Investigación de patrones de base de datos

public string Name { get { return (string)drCustomer["Name"]; } public DateTime MemberSince { get { return (DateTime)drCustomer["RegistrationDate"]; } public bool IsActive { get { return (bool)drCustomer["Active"]; } }

public class ConnectionStringFactory{ public static string GetConnectionString() { // Retrieve connection string from somewhere - config file, etc. }}

// This Application-code block illustrates how to create and initialize a Customer objectCustomer obCustomer = new Customer();Address obAddress = new Address( ... );obCustomer.CreateCustomer( "Yazan", obAddress, dtDON );

// CustomerCollection class that only contain objects of type Employeepublic class CustomerCollection : System.Collections.CollectionBase{ /* Constructors */ public CustomerCollection() {}

/* IList interface implementation */

// The Add method declaration permits only Customer objects to be added public void Add( Customer obCust ) { this.List.Add( obCust ); }

// Implement a Remove method public void Remove( int nIndex ) { // Check if index is valid if ((nIndex < 0) || (nIndex > this.Count - 1)) throw new ArgumentOutOfRangeException( "nIndex", "Index is not valid");

this.List.RemoveAt( nIndex ); }

// Implement an indexer that returns only Employee objects (and not object of type Object) public Customer this[int nIndex] {

Page 9: Investigación de patrones de base de datos

get { return (Customer)this.List[nIndex]; } set { List[nIndex] = value; } }

private void CollectionBase_Click(object sender, System.EventArgs e){ // Create some employee obejcts Customer obCust1 = new Customer(); obCust1.CreateCustomer( ... );

Customer obCust2 = new Customer(); obCust2.CreateCustomer( ... );

// Create our specialized collection CustomerCollection coll = new CustomerCollection();

coll.Add( obCust1 ); coll.Add( obCust2 );}

c) DAO

Un objeto de acceso a datos (DAO) es un objeto que proporciona una interfaz abstracta a algún tipo de otro mecanismo de persistencia de base de datos. Por su aplicación en mapeo, esta llama a la capa de persistencia, DAO proporciona algunas operaciones de datos específicos sin exponer a los detalles de la base de datos. Este aislamiento es compatible con el principio de una sola responsabilidad. Separa qué datos accede a las necesidades de la aplicación, en términos de objetos específicos del dominio y tipos de datos (la interfaz pública de la DAO), de cómo estas necesidades pueden ser satisfechas con un DBMS específico, esquema de base de datos, etc.

Ejemplo:Un ejemplo muy común de DAO se encuentra dentro del marco de trabajo de J2EE que frecuenta utilizar mucho esté Patrón para el acceso a datos. Un ejemplo muy común en J2EE es el siguiente Codigo.

import java.io.Serializable; public class User implements Serializable {

private static final long serialVersionUID = 1L;

private int userId;private String name;private String designation;private int age;

Page 10: Investigación de patrones de base de datos

public int getUserId() {

return userId;}public void setUserId(int userId) {

this.userId = userId;}public String getName() {

return name;}public void setName(String name) {

this.name = name;}public String getDesignation() {

return designation;}public void setDesignation(String designation) {

this.designation = designation;}public int getAge() {

return age;}public void setAge(int age) {

this.age = age;}

}

Lo siguiente es proporcionar una interface para no exponer sus elementos intentos

public interface UserDAO {public void insert(User user);public void update(User user);public void delete(int userId);public User[] findAll();public User findByKey(int userId);

}

Lo siguiente es implementar una clase con la interface creada, el cual nos permitirá definir las operaciones usando DAO

public class UserDAOImpl implements UserDAO {@Overridepublic void delete(int userId) {

// delete user from user table}

@Overridepublic User[] findAll() {

// get a list of all users from user tablereturn null;

}

@Overridepublic User findByKey(int userId) {

// get a user information if we supply unique useridreturn null;

Page 11: Investigación de patrones de base de datos

}

@Overridepublic void insert(User user) {

// insert user into user table}

@Overridepublic void update(User user) {

// update user information in user table}

}

d) Data Accesor

Encapsula acceso a datos físicos en componentes separados, exponiendo solamente sus operaciones lógicas. El código de la aplicación se encuentra desacoplado de las operaciones de acceso a datos.

Úsese este patrón cuando:

Usted desea ocultar la complejidad de acceso a datos físicos y problemas de plataforma de la lógica de la aplicación. Este requisito es típico en aplicaciones distribuidas.

Usted quiere definir múltiples implementaciones de acceso a datos y elegir entre ellos en tiempo de ejecución. Por ejemplo, el descriptor de acceso de datos debe ofrecer la misma interfaz sin dejar de ser capaz de tener acceso a SQL Server, Oracle, Sybase, y así sucesivamente.

Ejemplo:/* IDataAccessor interface declaration. Each logical operation (i.e., ExecuteNonQuery) supports single and multiple SQL statements */public interface IDataAccessor{ // ExecuteNonQuery Int32 ExecuteNonQuery(String strCS, CommandType cmdType, String strCommandText ); Int32[] ExecuteNonQuery(String strCS, CommandType[] acmdType, String[] astrCommandText );

// ExecuteDataset DataSet ExecuteDataset(String strCS, CommandType cmdType, String strCommandText ); DataSet[] ExecuteDataset(String strCS, CommandType[] acmdType, String[] astrCommandText );

// ExecuteDataReader IDataReader ExecuteDataReader(String strCS, CommandType cmdType, String strCommandText ); IDataReader[] ExecuteDataReader(String strCS, CommandType[] acmdType, String[] astrCommandText );

Page 12: Investigación de patrones de base de datos

// ExecuteScalar Object ExecuteScalar(String strCS, CommandType cmdType, String strCommandText ); Object[] ExecuteScalar(String strCS, CommandType[] acmdType, String[] astrCommandText );}

public class OracleDataAccessor : IDataAccessor{ ...

/* Oracle-implementation of IDataAccessor */

// ExecuteNonQuery Int32 ExecuteNonQuery(String strCS, CommandType cmdType, String strCommandText ) { /* Use Oracle-specific ADO.NET classes such as OracleCommand, OracleDataAdapter, etc. */ }

Int32[] ExecuteNonQuery(String strCS, CommandType[] acmdType, String[] astrCommandText, ref Array[] asqlParam ) { /* Use Oracle-specific ADO.NET classes such as OracleCommand, OracleDataAdapter, etc. */ }

...}

public class SQLServerDataAccessor : IDataAccessor{ ...

/* SQL Server-implementation of IDataAccessor */

// ExecuteNonQuery Int32 ExecuteNonQuery(String strCS, CommandType cmdType, String strCommandText ) { /* Use SQL Server-specific ADO.NET classes such as SqlCommand, SqlDataAdapter, etc. */ }

Int32[] ExecuteNonQuery(String strCS, CommandType[] acmdType, String[] astrCommandText, ref Array[] asqlParam ) { /* Use SQL Server-specific ADO.NET classes such as SqlCommand, SqlDataAdapter, etc. */ }}

Page 13: Investigación de patrones de base de datos

// Use a factory (not shown) to create a SQL Server data accessorIDataAccessor obSQLServer = new DBAccessFactory( eAccessor.SQLServer);

// Access dataobSQLServer.ExecuteNonQuery( strConn, CommandType.Text, "select * from T1" );

// Use a factory (not shown) to create an Oracle data accessorIDataAccessor obOracle = new DBAccessFactory( eAccessor.Oracle);

// Access dataobOracle.ExecuteNonQuery( strConn, CommandType.Text, "select * from T2" );

Domain Object Assembler

Patrón que prueba, persiste y elimina objetos usando un marco de trabajo de una fábrica uniforme.

Úsese este patrón cuando:

Necesites definir un objeto de dominio común, mapeando infraestructuras que sean responsables de poblar, persistir y eliminar objetos de dominio.

Necesites definir detalles de mapeo personalizados pata objetos de dominio individuales o entidades de base de datos.

Ejemplo en C#En este ejemplo, el DomainObjectAssembler interactua directamente con la base de datos usando ADO.NET representa selecciones utilizando la cláusula SQL WHERE mientras que las operaciones de actualización se representan utilizando mapas (hashtable) que contienen los nombres y valores de las columnas para actualizar.

/* When a client initializes a DomainObjectAssember, it is responsible for plugging in specific factory implementations, a database connection string, and the name of the table where data resides */public class Assembler{ // Data members private string strConnection = ""; private string strTableName = ""; private ISelectionFactory obSelectionFactory = null; private IUpdateFactory obUpdateFactory = null; private IDomainObjectFactory obDomainObjectFactory = null;

// Save parameters public Assembler(string conn, string table, ISelectionFactory sel, IUpdateFactory upd, IDomainObjectFactory dof) { strConnection = conn; strTableName = table; obSelectionFactory = sel;

Page 14: Investigación de patrones de base de datos

obUpdateFactory = upd; obDomainObjectFactory = dof; }

// Public interface

// Read domain objects that correspond to the given identity object public ArrayList Read(object obIdentity) { // Get the selection clause string strWhereClause = obSelectionFactory.NewSelection( obIdentity );;

// Execute query against database string strSQL = "select * from " + strTableName + strWhereClause; DataTable dt = ExecuteSQL( strSQL );

// Iterate through the result set and create a domain object for each row ArrayList alDomainObjects = new ArrayList(); foreach (DataRow row in dt.Rows) { // Use the domain object factory to create a domain object from this row alDomainObjects.Add( obDomainObjectFactory.NewDomainObject( row ) ); } return alDomainObjects; }

// Write a domain object that corresponds to the given identity object public void Write(object obIdentity) { // Query database table to see if any row matches the suppled identity object // This is used to determine whether an UPDATE or an INSERT is required string strWhereClause = obSelectionFactory.NewSelection( obIdentity ); string strSQL = "select * from" + strTableName + strWhereClause; DataTable dt = ExecuteSQL( strSQL ); string strSQLAction = (dt.Rows.Count > 0)? "UPDATE" : "INSERT";

// Use the update factory to generate a map of updatable values Hashtable htUpdateMap = obUpdateFactory.NewUpdate( obIdentity );

// Loop over the map and use strSQLAction (and strWhereClause if necessary) to generate // the update/insert SQL statement // ...

// Finally, issue the update/insert operations ExecuteSQL( strSQL ); }

// Delete domain objects that correspond to the given identity object

Page 15: Investigación de patrones de base de datos

public void Delete(object obIdentity) { // Get the selection clause and construct a DELETE statement string strWhereClause = obSelectionFactory.NewSelection( obIdentity ); string strSQL = "DELETE from T " + strWhereClause;

// Issue the delete statement ExecuteSQL( strSQL ); }

// Helper private DataTable ExecuteSQL( string str ) { ... }}

Todo el código de ejemplo ha sido genérico que funciona enteramente en términos de ISelectionFactory, IUpdateFactory e IDomainObjectAssembler. El código no hace ninguna referencia a ninguna de los tipos de objeto de dominio o entidades de base de datos. El siguiente conjunto de clases ha de definir los detalles de asignación para un tipo de objeto de dominio específico. El código que sigue trata de una tabla [DEPOSIT_ACCOUNT] y un objeto DepositAccount. La clase DepositAccount define el objeto principal de dominio en este ejemplo. Cada objeto DepositAccount corresponde a una fila de datos en la tabla [DEPOSIT_ACCOUNT]. También hay una clase DepostiAccountKey cuyas instancias se corresponden con los valores de clave principal para la tabla. DepositAccountKey actúa como el objeto de identidad para este ejemplo.

public class DepositAccount{ // Data members private string m_strAccountID = ""; private string m_strEmployeeID = ""; private string m_strBankName = ""; private string m_strReference = "";

// Constructor public DepositAccount(string eid, string aid, string bank, string reference ) { m_strEmployeeID = eid; m_strAccountID = aid; m_strBankName = bank; m_strReference = reference; }

// Properties public string AccountID { get { return m_strAccountID; } set { m_strAccountID = value; } } public string EmployeeID {

Page 16: Investigación de patrones de base de datos

get { return m_strEmployeeID; } set { m_strEmployeeID = value; } } public string BankName { get { return m_strBankName; } set { m_strBankName = value; } } public string Note { get { return m_strReference; } set { m_strReference = value; } } }

public class DepositAccountKey{ // Data members private string m_strAccountID = ""; private string m_strEmployeeID = "";

// Constructor public DepositAccountKey(string eid, string aid) { m_strEmployeeID = eid; m_strAccountID = aid; }

// Properties public string AccountID { get { return m_strAccountID; } set { m_strAccountID = value; } } public string EmployeeID { get { return m_strEmployeeID; } set { m_strEmployeeID = value; } }}

Las clases que siguen definir las implementaciones de fábrica que se conectan a una instancia DomainObjectAssembler para requisitos particulares para mapeo DepositAccount y DepositAccountKey casos a los contenidos de la tabla [DEPOSIT_ACCOUNT]. En conjunto, estas tres clases forman una sola extensión de marco de la DomainObjectAssmbler:

public interface ISelectionFactory{ string NewSelection ( object obIdentityObject );}

public interface IUpdateFactory{

Page 17: Investigación de patrones de base de datos

Hashtable NewUpdate ( object obIdentityObject );}

public interface IDomainObjectFactory{ ArrayList GetColumnNames(); object NewDomainObject( DataRow row );}

// This class implements ISelectionFactory and is responsible for translating a DepositAccountKey// identity object to a physical selection in the form of a SQL WHERE clausepublic class DepositAccountSelectionFactory : ISelectionFactory{ // ISelectionFactory implementation public string NewSelection ( object obIdentityObject ) { // Get the deposit account key object DepositAccountKey key = (DepositAccountKey)obIdentityObject;

StringBuilder sb = new StringBuilder(); sb.AppendFormat( " WHERE EMPLOYEE_ID = {0} and ACCOUNT_ID = {1}", key.EmployeeID, key.AccountID ); return sb.ToString(); }}

// This class implements IDomainObjectFactory and is responsible for translating a row// of data from the [DEPOSIT_ACCOUNT] table to a new DepositAccount objectpublic class DepositAccountFactory : IDomainObjectFactory{

// IDomainObjectFactory implementation public object NewDomainObject( DataRow row ) { // Collect data from the supplied data row string strEmployeeID = (string)row["EMPLOYEE_ID"]; string strAccountID = (string)row["ACCOUNT_ID"]; string strBankName = (string)row["BANK_NAME"]; string strReference = (string)row["REFERENCE"];

// Create a new domain object based on data collected from the data row and return new object DepositAccount da = new DepositAccount(strEmployeeID, strAccountID, strBankName, strReference); return da; }

public ArrayList GetColumnNames() { ArrayList alColumns = new ArrayList(); alColumns.Add( "EMPLOYEE_ID" ); alColumns.Add( "ACCOUNT_ID" ); alColumns.Add( "BANK_NAME" );

Page 18: Investigación de patrones de base de datos

alColumns.Add( "REFERENCE" ); return alColumns; }}

Page 19: Investigación de patrones de base de datos

// This class implements IUpdateFactory that is responsible for generating a map

// of columns names and column values that. This map represents the domain object's// attributes in terms of the [DEPOSIT_ACCOUNT] tablepublic class DepositAccountUpdateFactory : IUpdateFactory{ // IUpdateFactory implementation public Hashtable NewUpdate ( object obIdentityObject ) { // Get the deposit account key object DepositAccount obAccount = (DepositAccount)obIdentityObject;

Hashtable map = new Hashtable(); map.Add( "EMPLOYEE_ID", obAccount.EmployeeID ); map.Add( "ACCOUNT_ID", obAccount.AccountID ); map.Add( "BANK_NAME", obAccount.BankName ); map.Add( "REFERENCE", obAccount.Note );

return map; }}

La clase DomainObjectAssembler define operaciones genéricas y tipos de retorno que eluden en tiempo de compilación de chequeo. Obviamente, esto podría potencialmente causar errores en tiempo de ejecución debido a los tipos incorrectos de los objetos de identidad o implementaciones de fábrica están aprobando en La DepositAccountAccessor es un contenedor que maneja una instancia DomainObjectAssembler y sus implementaciones de fábrica concreta:

public class DepositAccountAccessor{ // Data members private Assembler assembler = null;

// Constructors public DepositAccountAccessor() { ISelectionFactory sf = new DepositAccountSelectionFactory(); IUpdateFactory up = new DepositAccountUpdateFactory(); IDomainObjectFactory dof = new DepositAccountFactory();

// Now construct the deposit account assembler string strConn = "..."; string strTable = "..."; assembler = new Assembler( strConn, strTable, sf, up, dof ); }

public DepositAccount Read( string strEmpID, string strAcctID ) { // Create an identity object to identify the employee DepositAccountKey key = new DepositAccountKey( strEmpID, strAcctID );

Page 20: Investigación de patrones de base de datos

// Get all DepositAccount objects that match ArrayList alDepositAccounts = assembler.Read( key );

// Return the first matching object DepositAccount ob = (alDepositAccounts.Count == 0 )? null : (DepositAccount)alDepositAccounts[0]; return ob; }

public void Write( DepositAccount ob ) { // Create an identity object to identify the employee DepositAccountKey key = new DepositAccountKey( ob.EmployeeID, ob.AccountID );

assembler.Write( key ); }

public void Delete( DepositAccount ob ) { // Create an identity object to identify the employee DepositAccountKey key = new DepositAccountKey( ob.EmployeeID, ob.AccountID );

assembler.Delete( ob ); }}

Este bloque de código es el código de cliente que utiliza una DepositAccountAccessor:

// Get a domain object from database dataDepositAccountAccessor obAccessor = new DepositAccountAccessor();DepositAccount obAccount = obAccessor.Read( "A1", "B1");

// Modify the deposit account domain object then write it back to the databaseobAccount.Note = "Account is frozen";obAccessor.Write( obAccount );

Page 21: Investigación de patrones de base de datos

Referencias consultadas

“Singleton”, Artículo publicado 26 de enero de 2010 en la plataforma blogspot.mx:http://tratandodeentenderlo.blogspot.mx/2010/01/patrones-de-diseno-singleton.html

“Fachada”, Artículo publicado el 20 de septiembre del 2012 en el siguiente sitio de temas de programación: http://softwareyotrasdesvirtudes.com/2012/09/20/como-utilizar-el-patron-facade-fachada-en-bases-de-datos/

“Factory”, Articulo publicado por Ricard Lou Torrijos redactor de temas de programación del sitio: http://programacion.net/articulo/catalogo_de_patrones_de_diseno_j2ee__y_ii:_capas_de_negocio_y_de_integracion_243/8

“Data Access Object”, Artículo publicado por inteligencia colectiva libre en Wikipedia.org en inglés: http://en.wikipedia.org/wiki/Data_access_object

“Active Record Pattern”, Artículo publicado por inteligencia colectiva libre en Wikipedia.org en inglés: http://en.wikipedia.org/wiki/Active_record_pattern

“Active Domain Object”, Artículo Publicado para la web diranieh.org: http://www.diranieh.com/DataAccessPatterns/ActiveDomainObject.htm

“Domain Object Assembler”, Artículo Publicado para la web diranieh.org: http://www.diranieh.com/DataAccessPatterns/DomainObjectAssembler.htm

“Data Accessor”, Artículo Publicado para la web diranieh.org: http://www.diranieh.com/DataAccessPatterns/DataAccessor.htm