Por qué poner una capa DAO sobre una capa de persistencia (como JDO o Hibernar)


Los Objetos de acceso a datos (DAOs) son un patrón de diseño común y recomendado por Sun. Pero los primeros ejemplos de DAOs de Java interactuaban directamente con bases de datos relacionales were estaban, en esencia, haciendo mapeo objeto-relacional (object). Hoy en día, veo DAOs encima de frameworks mature maduros como JDO e Hibernate, y me pregunto si eso es realmente una buena idea.

Estoy desarrollando un servicio web usando JDO como capa de persistencia, y estoy considerando si introducir o no DAOs. Me prever un problema cuando se trata de una clase particular que contiene un mapa de otros objetos:

public class Book {
    // Book description in various languages, indexed by ISO language codes
    private Map<String,BookDescription> descriptions;
}

JDO es lo suficientemente inteligente como para asignar esto a una restricción de clave foránea entre las tablas "BOOKS" y "BOOKDESCRIPTIONS". Carga de forma transparente los objetos BookDescription (utilizando carga lenta, creo) y los persiste cuando se persiste el objeto Book.

Si tuviera que introducir una "capa de acceso a datos" y escribir una clase como BookDao, y encapsular todo el código JDO dentro de esto, entonces ¿la carga transparente de los objetos secundarios de este JDO no estaría eludiendo la capa de acceso a datos? Por coherencia, no deberían cargarse y persistir todos los objetos BookDescription a través de algún objeto BookDescriptionDao (o BookDao.loadDescription method)? Sin embargo, refactorizar de esa manera haría que manipular el modelo fuera innecesariamente complicado.

Así que mi pregunta es, ¿qué hay de malo en llamar a JDO (o Hibernar, o cualquierM que te apetezca) directamente en la capa de negocios? Su sintaxis ya está bastante conciso, y es independiente del almacén de datos. ¿Cuál es la ventaja, si la hay, de encapsularla en Objetos de Acceso a datos?

Author: Todd Owen, 2009-09-04

10 answers

Depende de cuáles sean los objetivos de tu capa. Pones una abstracción para suministrar un conjunto diferente de semántica sobre otro conjunto. En general, hay más capas para simplificar algunas cosas, como el desarrollo de mantenimiento futuro. Pero podrían tener otros usos.

Por ejemplo, una capa de DAO (o manejo de persistencia) sobre un código OR proporciona una funcionalidad especializada de recuperación y manejo de errores que no quería contaminar la lógica de negocio.

 9
Author: Preet Sangha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-04 10:31:10

Usted hace algunos puntos. Pero sin embargo uso una capa de Dao, he aquí por qué:

  1. Los accesos a la base de datos son llamadas a un sistema remoto. En todos estos casos (también servicio web, ajax, etc...), la granularidad de la interacción debe ser lo suficientemente grande. Muchas llamadas pequeñas matarían el rendimiento. Esta necesidad de rendimiento requiere a menudo una vista diferente del sistema, o capa (aquí, la capa Dao).

  2. A veces, su operación de persistencia es solo para cargar / guardar / eliminar un objeto. Un único Dao (o una superclase ; considere Genéricos) puede ser responsable de esto, por lo que no tiene que codificar estos métodos una y otra vez.
    Pero a menudo, también tiene necesidades específicas, como ejecutar una solicitud específica que no es creada automáticamente por el OR. Allí, codifica tu necesidad específica con un método Dao específico (la reutilización es a menudo posible).
    Tener necesidades regulares y específicas en la misma capa permite la reutilización (por ejemplo, la interceptación puede garantizar que una base de datos la conexión está abierta / comprometida cuando sea necesario).

 12
Author: KLE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-23 13:44:14

DAO ha perdido su significado con el tiempo.

Durante los días de J2EE cuando se convirtió en un patrón popular, un DAO era una clase en la que se podía atender simultáneamente a múltiples fuentes de datos - una base de datos de un proveedor, una base de datos de otro, un archivo - y proporcionar un solo lugar para empaquetar consultas para comunicarse por datos.

Había mucho margen para la reutilización, por lo que un objeto DAO para una entidad en particular bien puede extender un DAO abstracto que aloja el material reutilizable, que en sí mismo implementa una interfaz DAO.

Después de J2EE/EJB, los patrones DataMapper y DataSource (o para sistemas simples, ActiveRecord) se hicieron populares para realizar el mismo papel. Sin embargo, DAO se convirtió en una palabra de moda para cualquier objeto involucrado con la persistencia.

Hoy en día, el término 'DAO' se ha convertido tristemente en un sinónimo de "una clase que me permite comunicarme con mi base de datos".

Con OR / JPA, gran parte de la lógica para un verdadero DAO de la era J2EE se proporciona de forma inmediata.

En el caso de un último patrón de fuente de datos, EntityManager de JPA es similar a la fuente de datos, pero generalmente se proporciona a través de una definición XML PersistenceUnit y se crea una instancia a través de IoC.

Los métodos CRUD que alguna vez vivieron en un DAO o Mapeador ahora se pueden proporcionar exactamente una vez usando el patrón de repositorio. No hay necesidad de AbstractDAO-los productos OR son lo suficientemente inteligentes como para aceptar un Objeto () y saber dónde lo está persistiendo.

 11
Author: 8bitjunkie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-09 17:25:10

Cuando se utiliza una herramienta OR como JDO o JPA, los DAOs son un anti-patrón. En este caso, crear una "capa de acceso a datos" es completamente innecesario y solo agregará código adicional y complejidad a la base de código, lo que dificulta su desarrollo y mantenimiento.

Basado en mi experiencia previa, recomendaría el uso de una fachada estática simple, por ejemplo Persistence, para proporcionar una API de alto nivel y fácil de usar para operaciones relacionadas con la persistencia.

Entonces, puede usar una importación estática para obtener un acceso fácil a esos métodos en cualquier lugar que son útiles. Por ejemplo, podría tener código como el siguiente:


    List<Book> cheapBooks = 
        find("select b from Book where b.price < ?", lowPriceForBooks);
    ...
    Book b = new Book(...);
    persist(b);
    ...
    Book existingBook = load(Book.class, bookId);
    remove(existingBook);
    ...

El código anterior es lo más fácil y simple posible, y se puede probar fácilmente por unidad.

 6
Author: Rogério,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-04 12:09:35

Una palabra: transacciones

Tomemos la situación en la que tengo que realizar dos operaciones de actualización de datos en una sola transacción. Estas operaciones juntas forman una unidad lógica de trabajo. Mi lógica de negocios quiere expresarse en términos de esa unidad de trabajo, y no quiere molestarse con los límites de las transacciones.

Así que escribo un DAO. Tome este pseudo código usando transacciones de primavera e hibernar:

editado para eliminar HQL que estaba ofendiendo @Roger tanto, pero que no era relevante para el punto

@Transactional
public void doUnitOfWork() {
  // some persistence operation here
  // some other persistence operation here
}

My business logic llama a doUnitOfWork(), que inicia una transacción, realiza ambas operaciones de persistencia y luego confirma. No sabe ni se preocupa por la transacción, o qué operaciones se realizan.

Además, si el DAO implementa una interfaz con el método doUnitOfWork (), entonces la lógica de negocio puede codificar en la interfaz, lo que facilita la prueba unitaria.

Generalmente, yo siempre envuelvo mis datos operaciones de acceso en un DAO, y golpear una interfaz a su alrededor.

 6
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-04 16:50:23

Creo que la mayoría de los DAOs son agregados por personas por razones histéricas (históricas;]). Tiene razón en que inicialmente se entendieron como una encapsulación conveniente de la cola SQL requerida para realizar las operaciones CRUD en días anteriores a OR. Hoy en día, con una persistencia transparente, su papel es en gran medida redundante.

Lo que ahora es apropiado son los conceptos de Repositorios y Servicios:

Repositorio: Una clase que almacena una colección de métodos de consulta implementados en specific específico code (eg, Hibernate or JDO)

Normalmente puede crear un repositorio de clase base abstracta y luego proporcionar una implementación específica de OR en la que implementa todos los métodos de consulta en el código que es específico de su OR. Lo bueno de este enfoque es que puede crear una implementación de MockRepository para ayudar a probar su aplicación sin usar la base de datos.

Servicio: Clase que almacena una colección de métodos que pueden orquestar cambios/adiciones no triviales al objeto modelo (típicamente código independiente OR).

Esto ayuda a mantener su aplicación en gran medida independiente de OR - portar la aplicación a otro OR realmente solo implica la implementación de una nueva clase(es) de repositorio específica (s) de OR.

 3
Author: Volksman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-24 01:53:26

Supongo que el patrón "clase DAO por entidad" es absolutamente redundante para una capa de datos administrada por OR. En su lugar, la capa DAO debe estar compuesta por un conjunto de métodos CRUD uno para todos que operan en clases de entidades arbitrarias y un gran número de métodos que realizan operaciones más sofisticadas en datos. Si la funcionalidad es lo suficientemente grande, entonces la capa DAO debe dividirse en varias clases basadas en los criterios de dominio, lo que hace que el enfoque sea más similar al Arquitectura Orientada al Servicio.

 3
Author: Jiří Vypědřík,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-17 07:28:18

El propósito de toda esta introducción a las capas era hacer que el mantenimiento fuera fácil y simple.

  1. Capa de Acceso a datos
  2. Capa de negocio
  3. Capa de presentación

El propósito de la Capa 1st (Data Access Layer) es tratar con la lógica de la base de datos y evitar que la Capa de Negocio conozca cualquiera de los detalles de la base de datos.
La Capa de Acceso a datos utiliza POJO o EJBs (DAO) para implementar IoC y POJOEJBs utiliza Hibernate u mapping mapping para tratar realmente con el Capa de Base de Datos.
Por lo tanto, si desea que su lógica de negocio no debe preocuparse por qué, qué y cómo se utiliza, se accede y se actualiza una base de datos y desea que DAO se encargue de esto
DAO puede soportar la lógica de cambiar diferentes tablas para soportar la operación haciendo una serie de llamadas de hibernación.
En esencia, está implementando un enfoque por capas en la Capa de acceso a datos al romper su funcionalidad nuevamente en dos capas, también conocidas como DAO e Hibernar.

 3
Author: user3089214,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-11 13:01:47

Si usas un OR: Disfruta de su Soporte de Persistencia Transparente! No utilice DAOs para empaquetar API OR. Como bien se dijo aquí, los DAOs están antes que losMss. ORs ha introducido conceptos de OODBMS, como Persistencia Transparente y Persistencia por Accesibilidad. Usted tiene que tomar ventaja de eso, porque hará su vida más fácil y su código hermoso. Supongamos que están modelando departamentos y empleados... Un caso de uso podría ser crear un nuevo departamento, crear un nuevo empleado y agregar al empleado al departamento... ¿qué harías tú?

//start persistence context
...
Department dept1 = new Department("department1");
dept1.addEmployee(new Employee("José", 10503f));

em.persist(dept1);
...
//close persistence context

Departamento, Empleado y su relación son persistentes ahora.

Supongamos que ahora tiene que agregar un Empleado existente y un Departamento existente... ¿qué harías? bastante simple:

//start persistence context
...
Department aDepart = hibernateSession.load(Department.class, dId);
Employee anEmployee = hibernateSession.load(Employee.class, eId);

aDepart.addEmployee(anEmployee);     
...
//close persistence context

Bastante simple gracias a la Persistencia Transparente y Persistencia por Accesibilidad que implementa Hibernate (como otrosMs). No DAOs en absoluto.

Simplemente codifica tu modelo de dominio y piensa como eres persistiendo en la memoria. Con una buena estrategia de mapeo, el OR persistirá de forma transparente lo que haces en la memoria.

Más ejemplos aquí: http://www.copypasteisforword.com/notes/hibernate-transparent-persistence http://www.copypasteisforword.com/notes/hibernate-transparent-persistence-ii

 1
Author: Enrique Molinari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-16 14:20:25

En realidad debe ser más simple de lo que todas estas respuestas hacen que sea. Estos patrones tienen que ver con capas. Usted no quiere referencias circulares a hacer capas que solo pueden saber acerca de las cosas por encima de ellos. Desea que su código de servicio pueda hacer referencia a todos y cada uno de los Servicios, que su código de servicio pueda hacer referencia a todos y cada uno de los DAOs.

  1. DAO
  2. Servicio
  3. UICode

Con los POJOs pasando de arriba a abajo.

 0
Author: andersonbd1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-04 12:18:17