2012-03-31 26 views
12

Digamos que tenemos un par de entidades que queremos persistir utilizando objetos DAO. Así que implementan la interfaz correcta por lo que terminamos conPatrón de diseño DAO

class JdbcUserDao implements UserDao{ 
//... 
} 

class JdbcAddressDao implements AddressDao{ 
//... 
} 

Así que si quiero ser capaz de cambiar las implementaciones de persistencia de JDBC para la APP (por ejemplo), y viceversa, necesitaría tener JPAUserDao y JPAAddressDao ... Es decir, si tuviera 20 entidades y decidiera cambiar las implementaciones (usando el contenedor DI), tendría que cambiar cada implementación de Jdbc con código JPA.

Ahora podría ser que no he entendido bien cómo funciona DAO, pero ... Si sólo tenía

class JdbcDaoImpl implements UserDao,AddressDao{ 
//... 
} 

que había entonces tienen todas las implementaciones JDBC en una clase, y las implementaciones de conmutación sería una pieza de pastel. Además, el recuento de DaoImpl es igual al número de interfaces Dao. ¿Por qué no simplemente agruparlos por implementación (jdbc, JTA, JPA ...) y tener todo bajo una sola clase?

Gracias de antemano.

+3

La misma razón por la que no codifican a cabo su aplicación en un gran 'main()' Método: separación de las preocupaciones. (Por cierto, nadie le impide codificar un 'JdbcDaoBase' abstracto que contenga un código común y lo amplíe en su' Dao') – rsp

+0

¿Por qué debería ser más fácil reemplazar 500 métodos en 1 clase que en 100 clases? –

Respuesta

20

Tener una única clase implementar cada interfaz DAO en toda la aplicación sería un diseño bastante malo.

Un patrón más típico es tener una interfaz BaseDAO (también a menudo llamado GenericDAO) y tienen un JPABaseDAO, JDBCBaseDAO etc. Estas clases de base contendrán métodos como encontrar/obtener/leer, guardar/tienda/persistir, actualizar/modificar y eliminar/eliminar/purgar.

interfaces de DAO específicos como UserDAO continuación heredan de BaseDAO e implementaciones concretas como JPAUserDAO se extiende desde JPABaseDAO.

Una interfaz BaseDAO podría tener este aspecto:

public interface BaseDAO <T> {  
    T getByID(Long ID); 
    T save(T type); 
    T update(T type); 
    void delete(T type); 
} 

Y una interfaz UserDAO:

public interface UserDAO extends BaseDAO<User> { 
    List<User> getAllAuthorized(); 
} 

sencillísimas ejemplo de un JPABaseDAO la implementación de esta interfaz:

@Stateless 
public class JPABaseDAO<T> implements BaseDAO<T> { 

    @PersistenceContext 
    private EntityManager entityManager; 

    private final Class<T> entityType; 

    @SuppressWarnings("unchecked") 
    public JPABaseDAO() { 
     this.entityType = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 
    } 

    @Override 
    public T getByID(Long ID) { 
     return entityManager.find(entityType, ID); 
    } 

    @Override 
    public T save(T type) { 
     return entityManager.persist(type);   
    } 

    @Override 
    public T update(T type) {   
     return entityManager.merge(type); 
    } 

    @Override 
    public void delete(T type) { 
     entityManager.remove(entityManager.contains(type) ? type : entityManager.merge(type)); 
    } 

} 

Y algunos muestra UserDAO implementación que heredaría de él:

@Stateless 
public class JPAUserDAO extends JPABaseDAO<User> implements UserDAO { 

    @PersistenceContext 
    private EntityManager entityManager; 

    @Override 
    public List<User> getAllAuthorized() { 
     return entityManager.createNamedQuery("User.getAllAuthorized", User.class) 
          .getResultList(); 
    } 
} 

En la práctica, la clase base a menudo pueden hacer algunas otras cosas de forma transparente, por ejemplo, comprobar si una entidad implementa algún tipo de Auditable interfaz, y automáticamente ajustar la fecha y el usuario que lo modificó , etc.

Al usar EJB para implementar sus DAO, una estrategia para cambiar las implementaciones sería poner todas las implementaciones JDBC en un paquete y todas las implementaciones JPA en el otro. Luego solo incluya solo un paquete de implementación en su compilación.

+0

Excelente, muchas gracias. ¿Qué hay de las operaciones CRUD que involucran múltiples tablas? ¿Podría, por ejemplo, ejecutar una instrucción select para obtener un objeto y usarlo para llamar al CRUD de otro DAO impl, o quizás crear algún tipo de DAO híbrido alienígena? Por cierto. me has sido de gran ayuda, muy apreciado. – Mercurial

+1

CRUD o cualquier operación que involucre múltiples entidades/tablas a menudo son manejadas por Servicios que agregan múltiples DAO. En EJB estará automáticamente dentro del mismo contexto de persistencia incluso si llama a varios DAO (se propaga). Otra posibilidad es que si las entidades están asociadas (el Usuario tiene una Casa), solo necesita un DAO para un Usuario y JPA buscará/guardará/actualizará las casas automáticamente desde sus objetos de Usuario. –

+1

Sí, agradable. Este enfoque es uno que seguí en varios proyectos. Demostró funcionar bastante bien y estable. Lo describo en detalle aquí: http://codeblock.engio.net/?p=180 – bennidi

1

El objetivo de Dependency Injection es facilitar el cambio entre implementaciones y desacoplar al usuario del proveedor. Por lo tanto, todos los marcos DI proporcionan alguna forma de "agrupar" varias implementaciones (aquí su grupo JDBC y su grupo JPA) y cambiarlas en un solo lugar.

También: generalmente la cantidad de consumidores (en su caso: cierta lógica de negocio que trabaja con usuarios y direcciones) suele ser mayor que la cantidad de DAO que el marco DI desacoplará la mayoría de las cosas para usted de todos modos. Supongamos: 50 beans comerciales, dos interfaces y dos implementaciones para cada interfaz (4 en total): incluso la DI básica se ocupará de los 50. Usar la agrupación reducirá a la mitad ese resto restante.

+0

¿Podría explicar la parte "También", por favor? Muchas gracias. – Mercurial

+0

@ user1304844: Me gustaría, pero no sé qué no está claro. –

+0

"incluso la DI básica se encargará de los 50. Usar la agrupación reducirá a la mitad ese resto restante para usted". - No entiendo esto. – Mercurial

0

Definitivamente hay posibilidades de implementar el patrón DAO de una manera ampliamente tecnológica, de modo que la tecnología de conmutación de persistencia o incluso la mezcla de múltiples tecnologías sea factible. Este artículo presenta un esquema de implementación que incluye el código fuente en github.

http://codeblock.engio.net/?p=180