Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Contexto
El acceso a los datos vara dependiendo de la fuente de los datos. El acceso al almacenamiento
persistente, como una base de datos, vara en gran medida dependiendo del tipo de
almacenamiento (bases de datos relacionales, bases de datos orientadas a objetos, ficheros
planos, etc.) y de la implementacin del vendedor.
Problema
Muchas aplicaciones de la plataforma J2EE en el mundo real necesitan utilizar datos persistentes
en algn momento. Para muchas de ellas, este almacenamiento persistente se implementa
utilizando diferentes mecanismos, y hay marcadas diferencias en los APIS utilizados para acceder
a esos mecanismos de almacenamiento diferentes. Otras aplicaciones podran necesitar acceder
a datos que residen en sistemas diferentes. Por ejemplo, los datos podran residir en sitemas
mainframe, repositorios LDAP, etc. Otro ejemplo es donde los datos los proporcionan servicios a
travs de sistemas externos como los sistemas de integracin negocio-a-negocio (B2B), servicios
de tarjetas de crdito, etc.
Normalmente, las aplicaciones utilizan componentes distribuidos y compartidos como los beans
de entidad para representar los datos persistentes. Se considera que una aplicacin emplea
consistencia manejada por el bean (BMP) cuando sus beans de entidad acceden explcitamente
al almacenamiento persistente -- el bean de entidad incluye cdigo para hacer esto. Una
aplicacin con requerimientos sencillos podra por lo tanto utilizar beans de entidad en lugar de
beans de sesin o servlets para acceder al almacenamiento persistente y recuperar o modificar
los datos. O, la aplicacin podra usar beans de entidad con persistencia manejada por el
contenedor, y as dejar que el contenedor maneje los detalles de las transaciones y de la
persistencia.
Las aplicaciones pueden utilizar el API JDBC para acceder a los datos en un sistema de control de
bases de datos relacionales (RDBMS). Este API permite una forma estndar de acceder y
manipular datos en un almacenamineto persistente, como una base de datos ralacional. El API
JDBC permite a las aplicaciones J2EE utilizar sentencias SQL, que son el mtodo estndar para
acceder a tablas RDBMS. Sin embargo, incluso dentro de un entorno RDBMS, la sntaxis y
formatos actuales de las sentencias SQL podran variar dependiendo de la propia base de datos
en particular.
Incluso hay una mayor variacin con diferentes tipos de almacenamientos persistentes. Los
mecanimos de acceso, los APIs soportados, y sus caractersticas varian entre los diferentes tipos
de almacenamientos persistentes, como bases de datos relacionales, bases de datos orientadas
a objetos, ficheros planos, etc. Las aplicaciones que necesitan acceder a datos de un sistema
legal o un sistema dispar (como un mainframe o un servicio B2B) se ven obligados a utilizar APIs
que podran ser propietarios. Dichas fuentes de datos dispares ofrecen retos a la aplicacin y
potencialmente pueden crear una dependencia directa entre el cdigo de la aplicacin y el
cdigo de acceso a los datos. Cuando los componentes de negocio -- beans de entidad, beans de
sesin e incluso componentes de presentacin como servlets y beans de apoyo para pginas JSP
-- necesitan acceder a una fuente de datos, pueden utilizar el API apropiado para conseguir la
conectividad y manipular la fuente de datos. Pero introducir el cdigo de conectividad y de
acceso a datos dentro de estos componentes genera un fuerte acoplamiento entre los
componentes y la implementacin de la fuente de datos. Dichas dependencias de cdigo en los
componentes hace difcil y tedioso migrar la aplicacin de un tipo de fuente de datos a otro.
Cuando cambia la fuente de datos, tambin deben cambiar los componentes para manejar el
nuevo tipo de fuente de datos.
Causas
Los componentes como los beans de entidad controlados por el bean, los beans de
sesin, los servlets, y otros objetos como beans de apoyo para pginas JSP necesitan
recuperar y almacenar informacin desde almacenamientos persistentes y otras fuentes de
datos como sistemas legales, B2B, LDAP, etc.
Los APIs para almacenamiento persistente varan dependiendo del vendedor del
producto. Otras fuentes de datos podran tener APIS que no son estndar y/o propietarios.
Estos APIs y sus capacidades tambin varan dependiendo del tipo de almacenamiento -bases de datos relacionales, bases de datos orientadas a objetos, documentos XML, ficheros
planos, etc. Hay una falta de APIs uniformes para corregir los requrimientos de acceso a
sistemas tan dispares.
Los componentes normalmente utilizan APIs propietarios para acceder a sistemas
externos y/o legales para recuperar y almacenar datos.
La portabilidad de los componentes se ve afectada directamente cuando se incluyen APIs
y mecanismos de acceso especficos.
Los componentes necesitan ser transparentes al almacenamiento persistente real o la
implementacin de la fuente de datos para proporcionar una migracin sencilla a diferentes
productos, diferentes tipos de almacenamiento y diferentes tipos de fuentes de datos.
Solucin
Utilizar un Data Access Object (DAO) para abstraer y encapsular todos los accesos a la
fuente de datos. El DAO maneja la conexin con la fuente de datos para obtener y
almacenar datos.
El DAO implementa el mecanismo de acceso requerido para trabajar con la fuente de datos. Esta
fuente de datos puede ser un almacenamiento persistente como una RDMBS, un servicio externo
como un intercambio B2B, un repositorio LDAP, o un servicio de negocios al que se accede
mediante CORBA Internet Inter-ORB Protocol (IIOP) o sockets de bajo nivel. Los componentes de
negocio que tratan con el DAO utilizan un interface simple expuesto por el DAO para sus clientes.
El DAO oculta completamente los detalles de implementacin de la fuente de datos a sus
clientes. Como el interface expuesto por el DAO no cambia cuando cambia la implementacin de
la fuente de datos subyacente, este patrn permite al DAO adaptarse a diferentes esquemas de
almacenamiento sin que esto afecte a sus clientes o componentes de engocio. Esencialmente, el
DAO acta como un adaptador entre el componente y la fuente de datos.
Estructura
La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrn
DAO:
Participantes y Responsabilidades
La siguiente figura muestra el diagrama de secuecnia de la interaccin entre los distintos
participantes en este patrn:
BusinessObject
BusinessObject representa los datos del cliente. Es el objeto que requiere el acceso a la
fuente
de
datos
para
obtener
y
almacenar
datos.
Podramos
implementar
un BusinessObject como un bean de sesin, un bean de entidad o cualquier otro objeto Java,
adems de como un Servlet o como un bean de apoyo.
DataAccessObject
DataAccessObject es el objeto principal de este patrn. DataAccessObject abstrae la
implementacin del acceso a datos subyacente al BusinessObject para permitirle un acceso
transparente a la fuente de datos. El BusinessObject tambin delega las operaciones de carga
y almacenamiento en el DataAccessObject.
DataSource
Representa la implementacin de la fuente de datos. Una fuente de datos podra ser una base de
datos como un RDBMS, un OODBMS, un repositorio XML, un fichero plano, etc. Tambin lo
pueden ser otros sitemas (mainframes/legales), servicios (servicio B2B u oficina de tarjetas de
crdito), o algn tipo de repositorio (LDAP).
TransferObject
Representa
un Transfer
Object utilizado
para
el
transporte
de
datos. DataAccessObject podra utilizar un Transfer Object para devolver los datos al
cliente. El DataAccessObject tambin podra recibir datos desde el cliente en un Transfer
Object para actualizar los datos en la fuente de datos.
Estrategias
Consecuencias
Permite
la
Transpariencia
Los objetos de negocio puede utilizar la fuente de datos sin conocer los detalles especficos
de su implementacin. El acceso es transparente porque los detalles de la implementacin
se ocultan dentro del DAO.
Permite
una
Migracin
ms
Fcil
Una capa de DAOs hace ms fcil que una aplicacin pueda migrar a una implementacin
de base de datos diferente. Los objetos de negocio no conocen la implementacin de datos
subyacente, la migracin implica cambios slo en la capa DAO. Adms, si se emplea la
estrategia de factoras, es posible proporcionar una implementacin de factoras concretas
por cada implementacin del almacenamiento subyacente. En este caso, la migracin a un
almacenamiento diferente significa proporcionar a la aplicacin una nueva implementacin
de la factora.
Reduce
la
Complejidad
del
Cdigo
de
los
Objetos
de
Negocio
Como los DAOs manejan todas las complejidades del acceso a los datos, se simplifica el
cdigo de los objetos de negocio y de otros clientes que utilizan los DAOs. Todo el cdigo
relacionado con la implementacin (como las sentencias SQL) estn dentro del DAO y no en
el objeto de negocio. Esto mejora la lectura del cdigo y la productividad del desarrollo.
Centraliza Todos los Accesos a Datos en un Capa Indenpendinte
Como todas las operaciones de acceso a los datos se ha delegado en los DAOs, esto se
puede ver como una capa que aisla el resto de la aplicacin de la implementacin de acceso
a los datos. Esta centralizacin hace que la aplicacin sea ms sencilla de mantener y de
manejar.
No
es
til
para
Persistencia
Manejada
por
el
Contenedor
Como el contenedor EJB maneja los beans de entidad con persistencia manejada por el
contenedor (CMP), sirve automticamente todo el acceso al almacenamiento persistente.
Las aplicacin que utilizan este tipo de beans no necesitan la capa DAO, ya que el servidor
de aplicaciones proporciona de forma transparente esta funcionalidad. Sin embargo, los
DAOS an son tiles cuando se necesita una combinacin de CMP (para beans de entidad) y
BMP (para beans de sein, servlets).
Aade
una
Capa
Extra
Los DAOs crean un capa de objetos adicional entre el cliente y la fuente de datos que
necesitamos disear e implementar para obtener los beneficios de este patrn. Pero para
obtener estos beneficios debemos pagarlos con un esfuerzo adicional.
Necesita
Disear
un
rbol
de
Clases
Cuando se utiliza una estrategia de factoras, necesitamos disear e implementar el rbol
de factoras concretas y el rbol de productos concretos producidos por las factoras.
Necesitamos justificar este esfuerzo adicional para ver si merece la pena dicha flexibilidad.
Esto incrementa la complejidad del diseo. Sin embargo, podemos elegir la implementacin
de la estrategia de factoras empezando primero con el patrn Factory Method, y luego
avanzar hasta el patrn Abstract Factory si es necesario.
Cdigo de Ejemplo
Implementar el Patrn Data Access Object
Abajo podemos ver el cdigo de un DAO de ejemplo para un objeto persistente que representa
informacin
de
un
cliente. CloudscapeCustomerDAO crea
un Transfer
Object Customer cuando se llama al mtodo findCustomer():
//
//
//
//
//
import java.sql.*;
public class CloudscapeCustomerDAO implements
CustomerDAO {
public CloudscapeCustomerDAO() {
// initialization
}
// The following methods can use
// CloudscapeDAOFactory.createConnection()
// to get a connection as required
public int insertCustomer(...) {
// Implement insert customer here.
// Return newly created customer number
// or a -1 on error
}
public boolean deleteCustomer(...) {
// Implement delete customer here
// Return true on success, false on failure
}
public Customer findCustomer(...) {
// Implement find a customer here using supplied
// argument values as search criteria
// Return a Transfer Object if found,
// return null on error or if not found
}
public boolean updateCustomer(...) {
// implement update record here using data
// from the customerData Transfer Object
// Return true on success, false on failure or
// error
}
public RowSet selectCustomersRS(...) {
// implement search customers here using the
// supplied criteria.
// Return a RowSet.
}
public Collection selectCustomersTO(...) {
// implement search customers here using the
// supplied criteria.
// Alternatively, implement to return a Collection
// of Transfer Objects.
}
...
}
Abajo podemos ver el cdigo para utilizar este DAO:
...
// create the required DAO Factory
DAOFactory cloudscapeFactory =
DAOFactory.getDAOFactory(DAOFactory.DAOCLOUDSCAPE);
// Create a DAO
CustomerDAO custDAO =
cloudscapeFactory.getCustomerDAO();
// create a new customer
int newCustNo = custDAO.insertCustomer(...);
// Find a customer object. Get the Transfer Object.
Customer cust = custDAO.findCustomer(...);
// modify the values in the Transfer Object.
cust.setAddress(...);
cust.setEmail(...);
// update the customer object using the DAO
custDAO.updateCustomer(cust);
// delete a customer object
custDAO.deleteCustomer(...);
// select all customers in the same city
Customer criteria=new Customer();
criteria.setCity("New York");
Collection customersList =
custDAO.selectCustomersTO(criteria);
// returns customersList - collection of Customer
// Transfer Objects. iterate through this collection to
// get values.
...
La siguiente figura representa el diagrama de clases para este ejemplo:
El siguiente fragmento de cdigo muestra parte de la clase DAOFactory. Esta factora produce
DAOs
como CustomerDAO, AccountDAO, OrderDAO,
etc.
Esta
estrategia
utiliza
el
patrn Factory Method en las factoras producidas por el Abstract Factory.
// Abstract class DAO Factory
public abstract class DAOFactory {
// List of DAO types supported by the factory
public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3;
...
// There will be a method for each DAO that can be
// created. The concrete factories will have to
// implement these methods.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
...
public
public
public
public
...
Customer findCustomer(...);
boolean updateCustomer(...);
RowSet selectCustomersRS(...);
Collection selectCustomersTO(...);
import java.sql.*;
public class CloudscapeCustomerDAO implements
CustomerDAO {
public CloudscapeCustomerDAO() {
// initialization
}
// The following methods can use
// CloudscapeDAOFactory.createConnection()
// to get a connection as required
public int insertCustomer(...) {
// Implement insert customer here.
// Return newly created customer number
// or a -1 on error
}
public boolean deleteCustomer(...) {
// Implement delete customer here
// Return true on success, false on failure
}
public Customer findCustomer(...) {
// Implement find a customer here using supplied
// argument values as search criteria
// Return a Transfer Object if found,
// return null on error or if not found
}
public boolean updateCustomer(...) {
// implement update record here using data
// from the customerData Transfer Object
// Return true on success, false on failure or
// error
}
public RowSet selectCustomersRS(...) {
// implement search customers here using the
// supplied criteria.
// Return a RowSet.
}
public Collection selectCustomersTO(...) {
//
//
//
//
}
...
}
La clase Transfer Object Customer del siguiente listado la utilizan los DAOs para enviar y
recibir datos desde los clientes. La utilizacin del patrn Transfer Object se explica con ms
detalles en la pgina Transfer Object: