Está en la página 1de 16

Data Access Object

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

Automatic DAO Code Generation


Como cada BusinessObject corresponde a un DAO especfico, es posible establecer relaciones
entre el BusinessObject, el DAO, y las implementaciones subyacentes (como en las tablas de
una RDBMS). Una vez que se han establecido las relaciones, es posible escribir una utilidad de
generacin-de-cdigo-especfica-de-aplicacin que genere el cdigo para todos los DAOs que
necesita la aplicacin. Los metadatos para generar el DAO pueden venir de un fichero descriptor
definido por el desarrollador. Como alternativa, el generador de cdigo puede inspeccionar la
base de datos y proporcionar los DAOs necesarios para acceder a ella.
Si los requerimientos de los DAOs son lo suficientemente complejos, debemos considerar la
utilizacin de herramientas de terceras partes que proporcionan un mapeo de objeto-a-relacional
para bases de datos RDBMS. Estas herramientas normalmente incluyen utilidades GUI para
mapear los objetos de negocio a objetos de almacenamiento persistente y adems definir los
DAOs intermedios. Estas herramientas generan el cdigo automticamente una vez que se
termina el mapeo, y podran proporcionar otras caractersticas valiosas como el cach de
resultados y de consultas, integracin con servidores de aplicaciones, integracin con otros
productos de terceras partes, etc.

Factory for Data Access Objects


El patrn DO se puede flexibilizar adoptando los patrones Abstract Factory [GoF] y Factory
Method [GoF].
Cuando el almacenamiento subyacente no est sujeto a cambios de una implemantacin a otra,
esta estrategia se puede implementar utilizando el patrn Factory Method para producir el
nmero de DAOs que necesita la aplicacin. En la siguiente figura podemos ver el diagrama de
clases para este caso:

Cuando el almacenamiento subyacente si est sujeto a cambios de una implementacin a otra,


esta estrategia se podra implementar usando el patrn Abstract Factory. Este patrn a su vez
puede construir y utilizar la implementacin Factory Method. En este caso, esta estrategia
proporciona un objeto factora abstracta de DAOs (Abstract Factory) que puede construir varios
tipos de factoras concretas de DAOs, cada factora soporta un tipo diferente de implementacin
del almacenamiento persistente. Una vez que obtenemos la factora concreta de DAOs para una
implementacin especfica, la utilizamos para producir los DAOs soportados e implementados en
esa implementacin.
En la siguiente figura podemos ver el diagrama de clases para esta estrategia. En l vemos una
factora base de DAOs, que es una clase abstracta que extienden e implementan las diferentes
factoras concretas de DAOs para soportar el acceso especfico a la implementacin del
almacenamiento. El cliente puede obtener una implementacin de la factora concreta del DAO
como una RdbDAOFactory y utilizarla para obtener los DAOs concretos que funcionan en la
implementacin
del
almacenamiento.
Por
ejemplo,
el
cliente
puede
obtener
una RdbDAOFactoryy
utilizarlas
para
obtener
DAOs
especfcios
como RdbCustomerDAO, RdbAccountDAO, etc. Los DAOs pueden extender e implementar una
clase base genrica (mostradas como DAO1 y DAO2) que describa especficamente los
requerimientos del DAO para el objeto de negocio que soporta. Cada DAO concreto es
responsable de conectar con la fuente de datos y de obtener y manipular los datos para el objeto
de negocio que soporta.

En la siguiente figura podemos ver el diagrama de secuencia para esta estrategia:

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():
//
//
//
//
//

CloudscapeCustomerDAO implementation of the


CustomerDAO interface. This class can contain all
Cloudscape specific code and SQL statements.
The client is thus shielded from knowing
these implementation details.

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:

Implementar la Estrategia Factory for Data Access Objects

Utilizar el Patrn Factory Method


Consideremos un ejemplo donde hemos implementado esta estrategia en la que una factora de
DAOs produce muchos DAOs para una nica implementacin de una base de datos (por ejemplo,
Oracle). La factora produce DAOs como CustomerDAO, AccountDAO, OrderDAO, etc. Abajo
podemos ver el diagrama de clases para este ejemplo:

Y aqu tenemos el cdigo de ejemplo para la factora de DAOs ( CloudscapeDAOFactory):


// Cloudscape concrete DAO Factory implementation
import java.sql.*;
public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";
// method to create Cloudscape connections
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}

Utilizar el Patrn Abstract Factory


Consideremos un ejemplo donde implementemos esta estrategia para tres bases de datos
diferenets. En este caso, se puede emplear el patrn Abstract Factory. En la siguiente figura
podemos ver el diagrama de clases para este ejmplo.

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 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;
}
}
}
El ejemplo de cdigo para CloudscapeDAOFactory se ve en el siguiente listado. La
implementacin para OracleDAOFactory y SybaseDAOFactory son similares excepto para
especifidades de cada implementacin, como el driver JDBC, la URL de la base de datos, y
diferencias en la sntaxis SQL, si existe// Cloudscape concrete DAO Factory implementation
import java.sql.*;
public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";
// method to create Cloudscape connections
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}
El interface CustomerDAO mostrado en el siguiente listado, define los mtodos DAO para los
objetos Customer persistentes que son implementados por todas las implementaciones de
DAOs
concretos
como CloudscapeCustomerDAO, OracleCustomerDAO,
y SybaseCustomerDAO.
Similares,
aunque
no
se
listan
aqu,
son
los
interfaces AccountDAO y OrderDAO que definen los metodos DAO para los objetos de
negocio Account y Order respectivamente.
// Interface that all CustomerDAOs must support
public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);

public
public
public
public
...

Customer findCustomer(...);
boolean updateCustomer(...);
RowSet selectCustomersRS(...);
Collection selectCustomersTO(...);

CloudscapeCustomerDAO implementa CustomerDAO como se ven en el siguiente listado. La


implementacin
de
los
otros
DAOs,
como CloudscapeOrderDAO, OracleCustomerDAO,OracleAccountDAO, etc. son similares:
//
//
//
//
//

CloudscapeCustomerDAO implementation of the


CustomerDAO interface. This class can contain all
Cloudscape specific code and SQL statements.
The client is thus shielded from knowing
these implementation details.

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.

}
...
}
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:

public class Customer implements java.io.Serializable {


// member variables
int CustomerNumber;
String name;
String streetAddress;
String city;
...
// getter and setter methods...
...
}
El siguiente ejemplo muestra la utilizacin del factora de DAOs y del DAO, Si la implementacin
cambiara de Cloudscape a otro producto, el nico cambio que tendramos que hacer es que el
mtodo getDAOFactory() llame a la factora adecuada.
...
// 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.
...

También podría gustarte