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. 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; } Integer company_id) throws Exception { UsersDAO usersDAO = new UsersDAO(). User user = usersDAO. } public User loadUser(int id) throws Exception{ UsersDAO usersDAO = new UsersDAO(). Lo que conseguimos es abstraer una capa de otra. String password.getUserById(id). Ejemplo: // Patrones auxiliares de acceso a datos (Facade). return user.getSelectedUser(). de forma que si una capa cambia no hace falta cambiar la otra.view. company_id).loadUser(this. return user.getUserId()). public class UsersFacade { public User loginUser(String userName. } //Uso de la Fachada UsersFacade uf = new UsersFacade().getUserByLoginPassword(userName. . User user = usersDAO. 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. este patrón actúa de Fachada. password.b) Fachada Como su propia traducción indica. uf. public static Connection createConnection() { } public CustomerDAO getCustomerDAO() { return new CloudscapeCustomerDAO(). public static final int SYBASE = 3. public static final String DBURL="jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB". public static final int ORACLE = 2.core. cada factoría soporta un tipo diferente de implementación del almacenamiento persistente.RmiJdbcDriver". Una vez que obtenemos la factoría concreta de DAOs para una implementación específica.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. } } } //Clase CloudscapeDAOFactory public class CloudscapeDAOFactory extends DAOFactory { public static final String DRIVER="COM. 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. public static DAOFactory getDAOFactory( int whichFactory) { switch (whichFactory) { case CLOUDSCAPE: return new CloudscapeDAOFactory(). Los objetos de negocio no conocen la implementación de datos subyacente. la utilizamos para producir los DAOs soportados e implementados en esa implementación.cloudscape. case SYBASE : return new SybaseDAOFactory(). public abstract AccountDAO getAccountDAO(). public abstract CustomerDAO getCustomerDAO(). 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. . la migración implica cambios sólo en la capa DAO. case ORACLE : return new OracleDAOFactory(). public abstract class DAOFactory { public static final int CLOUDSCAPE = 1. Ejemplo: // Patrones auxiliares de acceso a datos (Factory). default : return null. public abstract OrderDAO getOrderDAO(). import org. public class Employee extends Model { static{ validatePresenceOf("first_name". deberá incluir funciones Insert.simple. propiedades que corresponde directamente a las columnas que se encuentran en la tabla de la base de datos. } public OrderDAO getOrderDAO() { return new CloudscapeOrderDAO().slf4j.activejdbc.examples.activejdbc.mysql. package activejdbc.examples. "root". "p@ssw0rd"). "last_name"). } } 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. ActiveJDBC es ligero.class).Model.jdbc.simple. . el cual es inspirado en Ruby on rails Active Record.javalite. import org. Update y Delete y adempas.} public AccountDAO getAccountDAO() { return new CloudscapeAccountDAO().slf4j. Este patrón es comúnmente usado por herramientas para persistis objetos y además en los Object-Relational Mapping (ORM). "jdbc:mysql://localhost/test". La interface del objeto que conforma a este patrón. Ejemplo: El lenguaje Java implementa este patrón a través de la librería ActiveJDBC.Base.LoggerFactory. } } package activejdbc. import org.Logger. import org.open("com. public static void main(String[] args) { Base.Driver". public class SimpleExample { final static Logger logger = LoggerFactory.getLogger(SimpleExample.javalite. rápido y pequeño y no requiere ninguna configuración. logger. "Steinbeck"). Created employee:"). logger. updateEmployee(). deleteEmployee(). Created employee:").set("last_name". "John").toString()). } private static void createEmployee() { Employee e = new Employee().saveIt(). e. Deleted employee:"). e.createEmployee().info(e. logger. "John"). deleteAllEmployees(). "Doe").delete().set("last_name". } private static void deleteAllEmployees() { Employee. "John"). } private static void updateEmployee() { Employee e = Employee.set("first_name". e. Base. Updated employee:").info("=========> selectAllEmployees().info("=========> selectEmployee(). En otras palabras.deleteAll(). createEmployee().saveIt(). logger. e. logger. } private static void deleteEmployee() { Employee e = Employee. } b) Active Domain Object Encapsula modelo de datos y acceso a datos detalles dentro de un objeto de dominio correspondiente.info("Employees list: " + Employee.findFirst("first_name = ?". un Active Domain Object abstrae la semántica del almacén de datos subyacente (es decir.findFirst("first_name = ?". Deleted all employees:").info("=========> selectAllEmployees(). logger.info("=========> selectAllEmployees(). "John"). } } private static void selectAllEmployees() { logger. } private static void selectEmployee() { Employee e = Employee. SQL Server) y la tecnología de acceso de datos .findAll()).close().findFirst("first_name = ?".info("=========> selectEmployee(). e. // Used by /* Constructors */ public Customer() { // Acquire the connection string from a connection-string factory-object m_strConnection = ConnectionStringFactory. } /* Data access methods */ public System. 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 */ . the data accessor object to access database private System. Ejemplo: public class Customer { /* Data members */ private string m_strConnection = "". } public int CreateCustomer( string strName.DataRow drCustomer = null.DataRow GetCustomer( int nID ) { // Use data access helper components to retrieve customer data via a stored procedure drCustomer = .GetConnectionString(). ADO.Data.Data. // Return customer information return drCustomer.subyacente (es decir...NET) y proporciona una sencilla interfaz de programación para recuperar y operar en los datos. } } public class ConnectionStringFactory { public static string GetConnectionString() { // Retrieve connection string from somewhere ..1)) throw new ArgumentOutOfRangeException( "nIndex". this. } } // This Application-code block illustrates how to create and initialize a Customer object Customer obCustomer = new Customer(). Address obAddress = new Address( ..List. etc. } // Implement an indexer that returns only Employee objects (and not object of type Object) public Customer this[int nIndex] { . ).RemoveAt( nIndex ).Collections.public string Name { get { return (string)drCustomer["Name"].List. // CustomerCollection class that only contain objects of type Employee public class CustomerCollection : System. } public bool IsActive { get { return (bool)drCustomer["Active"]. obAddress.config file.Count . "Index is not valid").CollectionBase { /* Constructors */ public CustomerCollection() {} /* IList interface implementation */ // The Add method declaration permits only Customer objects to be added public void Add( Customer obCust ) { this. dtDON ).Add( obCust ).CreateCustomer( "Yazan". } // Implement a Remove method public void Remove( int nIndex ) { // Check if index is valid if ((nIndex < 0) || (nIndex > this. obCustomer. } public DateTime MemberSince { get { return (DateTime)drCustomer["RegistrationDate"]. EventArgs e) { // Create some employee obejcts Customer obCust1 = new Customer(). Un ejemplo muy común en J2EE es el siguiente Codigo. Este aislamiento es compatible con el principio de una sola responsabilidad. etc.. // Create our specialized collection CustomerCollection coll = new CustomerCollection().. obCust2. esquema de base de datos. } 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. DAO proporciona algunas operaciones de datos específicos sin exponer a los detalles de la base de datos. import java. Customer obCust2 = new Customer(). de cómo estas necesidades pueden ser satisfechas con un DBMS específico. esta llama a la capa de persistencia..Serializable. Separa qué datos accede a las necesidades de la aplicación. System. } set { List[nIndex] = value..io. . public class User implements Serializable { private static final long serialVersionUID = 1L. obCust1. Por su aplicación en mapeo. } private void CollectionBase_Click(object sender.Add( obCust1 ). en términos de objetos específicos del dominio y tipos de datos (la interfaz pública de la DAO).List[nIndex]. 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. String designation.CreateCustomer( . private private private private int userId.Add( obCust2 ). ). ). coll. int age. coll.} get { return (Customer)this.CreateCustomer( . String name. } @Override public User findByKey(int userId) { // get a user information if we supply unique userid . public User findByKey(int userId).name = name. } Lo siguiente es implementar una clase con la interface creada.public int getUserId() { return userId. el cual nos permitirá definir las operaciones usando DAO public class UserDAOImpl implements UserDAO { @Override public void delete(int userId) { // delete user from user table } @Override public User[] findAll() { // get a list of all users from user table return null. } public String getDesignation() { return designation. } } Lo siguiente es proporcionar una interface para no exponer sus elementos intentos public interface UserDAO { public void insert(User user). } public int getAge() { return age. public void delete(int userId).userId = userId.age = age. } public void setDesignation(String designation) { this. } public void setName(String name) { this. } public void setAge(int age) { this. } public void setUserId(int userId) { this. public void update(User user). } public String getName() { return name. public User[] findAll().designation = designation. exponiendo solamente sus operaciones lógicas. CommandType cmdType. ExecuteNonQuery) supports single and multiple SQL statements */ public interface IDataAccessor { // ExecuteNonQuery Int32 ExecuteNonQuery(String strCS. // ExecuteDataReader IDataReader ExecuteDataReader(String strCS. CommandType[] acmdType. . // ExecuteDataset DataSet ExecuteDataset(String strCS. CommandType cmdType. DataSet[] ExecuteDataset(String strCS.e. String[] astrCommandText ). Por ejemplo. el descriptor de acceso de datos debe ofrecer la misma interfaz sin dejar de ser capaz de tener acceso a SQL Server. String strCommandText ).return null. Usted quiere definir múltiples implementaciones de acceso a datos y elegir entre ellos en tiempo de ejecución. El código de la aplicación se encuentra desacoplado de las operaciones de acceso a datos. Este requisito es típico en aplicaciones distribuidas. String strCommandText ). Sybase. CommandType[] acmdType. String[] astrCommandText ).. Each logical operation (i. y así sucesivamente. Oracle. CommandType cmdType. Int32[] ExecuteNonQuery(String strCS. String strCommandText ). Ú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. Ejemplo: /* IDataAccessor interface declaration. } @Override public void insert(User user) { // insert user into user table } @Override public void update(User user) { // update user information in user table } } d) Data Accesor Encapsula acceso a datos físicos en componentes separados. } public class OracleDataAccessor : IDataAccessor { . /* SQL Server-implementation of IDataAccessor */ // ExecuteNonQuery Int32 ExecuteNonQuery(String strCS. SqlDataAdapter. Object[] ExecuteScalar(String strCS.. CommandType[] acmdType. */ } Int32[] ExecuteNonQuery(String strCS. String[] astrCommandText )..NET classes such as OracleCommand. String[] astrCommandText. etc. ref Array[] asqlParam ) { /* Use Oracle-specific ADO. etc. CommandType cmdType.. */ } } . /* Oracle-implementation of IDataAccessor */ // ExecuteNonQuery Int32 ExecuteNonQuery(String strCS. CommandType cmdType.NET classes such as OracleCommand. ref Array[] asqlParam ) { .IDataReader[] ExecuteDataReader(String strCS. CommandType cmdType. String strCommandText ) { /* Use SQL Server-specific ADO. // ExecuteScalar Object ExecuteScalar(String strCS. OracleDataAdapter. */ } Int32[] ExecuteNonQuery(String strCS.NET classes such as SqlCommand.. CommandType[] acmdType. String strCommandText ) { /* Use Oracle-specific ADO. public class SQLServerDataAccessor : IDataAccessor { . String[] astrCommandText. CommandType[] acmdType.. CommandType[] acmdType. String[] astrCommandText ). String strCommandText ). OracleDataAdapter.. etc. Úsese este patrón cuando: Necesites definir un objeto de dominio común. ISelectionFactory sel. a database connection string. IUpdateFactory upd. private IDomainObjectFactory obDomainObjectFactory = null. /* When a client initializes a DomainObjectAssember. private IUpdateFactory obUpdateFactory = null. CommandType. private string strTableName = "". "select * from T2" ). Necesites definir detalles de mapeo personalizados pata objetos de dominio individuales o entidades de base de datos. SqlDataAdapter.ExecuteNonQuery( strConn.ExecuteNonQuery( strConn. CommandType. string table. IDomainObjectFactory dof) . // Use a factory (not shown) to create an Oracle data accessor IDataAccessor obOracle = new DBAccessFactory( eAccessor.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./* Use SQL Server-specific ADO.Text.Oracle). */ } } // Use a factory (not shown) to create a SQL Server data accessor IDataAccessor obSQLServer = new DBAccessFactory( eAccessor.Text. private ISelectionFactory obSelectionFactory = null. // Access data obOracle. mapeando infraestructuras que sean responsables de poblar.NET classes such as SqlCommand. persiste y elimina objetos usando un marco de trabajo de una fábrica uniforme. and the name of the table where data resides */ public class Assembler { // Data members private string strConnection = "". Ejemplo en C# En este ejemplo. persistir y eliminar objetos de dominio. el DomainObjectAssembler interactua directamente con la base de datos usando ADO.SQLServer). // Access data obSQLServer. it is responsible for plugging in specific factory implementations. "select * from T1" ). etc. // Save parameters public Assembler(string conn. Domain Object Assembler Patrón que prueba. Add( obDomainObjectFactory. foreach (DataRow row in dt.NewUpdate( obIdentity ).NewSelection( obIdentity ).. // Iterate through the result set and create a domain object for each row ArrayList alDomainObjects = new ArrayList(). } // 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.Rows. string strSQLAction = (dt. issue the update/insert operations . } return alDomainObjects.Rows) { // Use the domain object factory to create a domain object from this row alDomainObjects.NewSelection( obIdentity ). upd. // Use the update factory to generate a map of updatable values Hashtable htUpdateMap = obUpdateFactory.{ } strConnection strTableName obSelectionFactory obUpdateFactory obDomainObjectFactory = = = = = conn.NewDomainObject( row ) ). // necessary) // // Loop over the map and use strSQLAction (and strWhereClause if to generate the update/insert SQL statement . string strSQL = "select * from" + strTableName + strWhereClause. sel. // Execute query against database string strSQL = "select * from " + strTableName + strWhereClause. table. // Finally.. DataTable dt = ExecuteSQL( strSQL ).Count > 0)? "UPDATE" : "INSERT". DataTable dt = ExecuteSQL( strSQL ).. 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. } // Properties public string AccountID { get { return m_strAccountID. m_strReference = reference. // Constructor public DepositAccount(string eid. DepositAccountKey actúa como el objeto de identidad para este ejemplo. m_strAccountID = aid. IUpdateFactory e IDomainObjectAssembler. También hay una clase DepostiAccountKey cuyas instancias se corresponden con los valores de clave principal para la tabla. } } Todo el código de ejemplo ha sido genérico que funciona enteramente en términos de ISelectionFactory. } . El código no hace ninguna referencia a ninguna de los tipos de objeto de dominio o entidades de base de datos. 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]... private string m_strEmployeeID = "". m_strBankName = bank. El siguiente conjunto de clases ha de definir los detalles de asignación para un tipo de objeto de dominio específico. private string m_strReference = "". El código que sigue trata de una tabla [DEPOSIT_ACCOUNT] y un objeto DepositAccount.ExecuteSQL( strSQL ). public class DepositAccount { // Data members private string m_strAccountID = "". // Issue the delete statement ExecuteSQL( strSQL ).NewSelection( obIdentity ). private string m_strBankName = "". } // Delete domain objects that correspond to the given identity object public void Delete(object obIdentity) { // Get the selection clause and construct a DELETE statement string strWhereClause = obSelectionFactory. string bank. } // Helper private DataTable ExecuteSQL( string str ) { . string strSQL = "DELETE from T " + strWhereClause. string reference ) { m_strEmployeeID = eid. string aid. } } public string Note { get { return m_strReference. } set { m_strBankName = value. } set { m_strEmployeeID = value. } } public string EmployeeID { get { return m_strEmployeeID. En conjunto. } } public string BankName { get { return m_strBankName. } // Properties public string AccountID { get { return m_strAccountID.set { m_strAccountID = value. private string m_strEmployeeID = "". string aid) { m_strEmployeeID = eid. } 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]. } } } public class DepositAccountKey { // Data members private string m_strAccountID = "". estas tres clases forman una sola extensión de marco de la DomainObjectAssmbler: public interface ISelectionFactory { string NewSelection ( object obIdentityObject ). m_strAccountID = aid. . } set { m_strReference = value. // Constructor public DepositAccountKey(string eid. } set { m_strAccountID = value. } } public string EmployeeID { get { return m_strEmployeeID. AppendFormat( " WHERE EMPLOYEE_ID = {0} and ACCOUNT_ID = {1}". 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 clause public class DepositAccountSelectionFactory : ISelectionFactory { // ISelectionFactory implementation public string NewSelection ( object obIdentityObject ) { // Get the deposit account key object DepositAccountKey key = (DepositAccountKey)obIdentityObject.AccountID ). strReference).ToString(). strAccountID. StringBuilder sb = new StringBuilder().} public interface IUpdateFactory { Hashtable NewUpdate ( object obIdentityObject ). } public ArrayList GetColumnNames() { . } } // This class implements IDomainObjectFactory and is responsible for translating a row // of data from the [DEPOSIT_ACCOUNT] table to a new DepositAccount object public class DepositAccountFactory : IDomainObjectFactory { // IDomainObjectFactory implementation public object NewDomainObject( DataRow row ) { // Collect data from the supplied data row string strEmployeeID = (string)row["EMPLOYEE_ID"]. string strReference = (string)row["REFERENCE"]. string strAccountID = (string)row["ACCOUNT_ID"]. } public interface IDomainObjectFactory { ArrayList GetColumnNames(). key. strBankName. // Create a new domain object based on data collected from the data row and return new object DepositAccount da = new DepositAccount(strEmployeeID. key. return sb. sb.EmployeeID. return da. string strBankName = (string)row["BANK_NAME"]. alColumns. return alColumns. alColumns. .Add( "BANK_NAME" ). alColumns.Add( "ACCOUNT_ID" ).Add( "REFERENCE" ).} } ArrayList alColumns = new ArrayList().Add( "EMPLOYEE_ID" ). alColumns. } public DepositAccount Read( string strEmpID. obAccount. . 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. // Now construct the deposit account assembler string strConn = ".. map. map. obAccount.Add( "ACCOUNT_ID".".Add( "BANK_NAME". Obviamente. Hashtable map = new Hashtable(). obAccount.BankName ). map. string strTable = ".Add( "EMPLOYEE_ID". } return map. dof ). IDomainObjectFactory dof = new DepositAccountFactory(). IUpdateFactory up = new DepositAccountUpdateFactory(). string strAcctID ) { // Create an identity object to identify the employee DepositAccountKey key = new DepositAccountKey( strEmpID. strAcctID ). strTable.Note ). map.".// This class implements IUpdateFactory that is responsible for generating a map // of columns names and column values that.Add( "REFERENCE". This map represents the domain object's // attributes in terms of the [DEPOSIT_ACCOUNT] table public class DepositAccountUpdateFactory : IUpdateFactory { // IUpdateFactory implementation public Hashtable NewUpdate ( object obIdentityObject ) { // Get the deposit account key object DepositAccount obAccount = (DepositAccount)obIdentityObject. sf... assembler = new Assembler( strConn. } La clase DomainObjectAssembler define operaciones genéricas y tipos de retorno que eluden en tiempo de compilación de chequeo.EmployeeID ). // Constructors public DepositAccountAccessor() { ISelectionFactory sf = new DepositAccountSelectionFactory(). up.AccountID ).. obAccount. } Este bloque de código es el código de cliente que utiliza una DepositAccountAccessor: // Get a domain object from database data DepositAccountAccessor obAccessor = new DepositAccountAccessor(). } public void Delete( DepositAccount ob ) { // Create an identity object to identify the employee DepositAccountKey key = new DepositAccountKey( ob. ob. assembler. . } public void Write( DepositAccount ob ) { // Create an identity object to identify the employee DepositAccountKey key = new DepositAccountKey( ob. // Modify the deposit account domain object then write it back to the database obAccount.AccountID ).Write( key ). DepositAccount obAccount = obAccessor.AccountID ).Note = "Account is frozen".Delete( ob ). obAccessor.EmployeeID.Write( obAccount ). // Return the first matching object DepositAccount ob = (alDepositAccounts. return ob.EmployeeID. ob.Count == 0 )? null : (DepositAccount)alDepositAccounts[0]. "B1").Read( key ).// Get all DepositAccount objects that match ArrayList alDepositAccounts = assembler.Read( "A1". } assembler. htm “Data Accessor”.html “Fachada”.Referencias consultadas “Singleton”.diranieh.org/wiki/Data_access_object “Active Record Pattern”.blogspot. Artículo Publicado para la web diranieh.wikipedia. Artículo publicado por inteligencia colectiva libre en Wikipedia. Artículo publicado por inteligencia colectiva libre en Wikipedia.org: http://www.org en inglés: http://en.com/DataAccessPatterns/DataAccessor.htm .org en inglés: http://en.org: http://www. Articulo publicado por Ricard Lou Torrijos redactor de temas de programación del sitio: http://programacion.org/wiki/Active_record_pattern “Active Domain Object”. Artículo publicado el 20 de septiembre del 2012 en el siguiente sitio de temas de programación: http://softwareyotrasdesvirtudes.org: http://www. Artículo Publicado para la web diranieh.mx: http://tratandodeentenderlo.com/DataAccessPatterns/DomainObjectAssembler.net/articulo/catalogo_de_patrones_de_diseno_j2ee__y_ii:_capa s_de_negocio_y_de_integracion_243/8 “Data Access Object”.com/2012/09/20/como-utilizar-el-patron-facadefachada-en-bases-de-datos/ “Factory”.mx/2010/01/patrones-de-diseno-singleton.com/DataAccessPatterns/ActiveDomainObject.wikipedia. Artículo Publicado para la web diranieh.diranieh.htm “Domain Object Assembler”. Artículo publicado 26 de enero de 2010 en la plataforma blogspot.diranieh.
Report "Investigación de patrones de base de datos "