impl generic ejemplo java spring architecture jpa dao

java - generic - spring boot hibernate



Capas DAO y Servicio(JPA/Hibernate+Spring) (5)

Estoy diseñando una nueva aplicación basada en JPA / Hibernate, Spring y Wicket. La distinción entre las capas DAO y Service no me resulta tan clara. Según Wikipedia, DAO es

un objeto que proporciona una interfaz abstracta a algún tipo de base de datos o mecanismo de persistencia, proporcionando algunas operaciones específicas sin exponer detalles de la base de datos.

Me preguntaba si un DAO podría contener métodos que realmente no tienen que hacer mucho con el acceso a los datos, pero que son mucho más fáciles de ejecutar con una consulta. Por ejemplo, "obtener una lista de todas las aerolíneas que operan en un cierto conjunto de aeropuertos"? Me parece que es más un método de capa de servicio, pero no estoy seguro de si el uso de JPA EntityManager en la capa de servicio es un ejemplo de buena práctica.


Dao es un objeto de acceso a datos. Almacena, actualiza y selecciona entidades en la base de datos. El objeto del administrador de la entidad se usa para eso (al menos en jpa abierto). También puede ejecutar consultas con este administrador de entidades. No es sql sino JPQL (lenguaje de consulta de persistencia de Java).

Ejemplo simple:

emf = Persistence.createEntityManagerFactory("localDB"); em = emf.createEntityManager(); Query q = em.createQuery("select u from Users as u where u.username = :username", Users.class); q.setParameter("username", username); List<Users> results = q.getResultList(); em.close(); emf.close();


Este article de Adam Bien podría ser útil.


Tradicionalmente, escribiría interfaces que definen el contrato entre su capa de servicio y la capa de datos. Luego escribe implementaciones y estas son sus DAO.

De vuelta a tu ejemplo. Asumiendo que la relación entre el aeropuerto y la aerolínea es muchos para muchos con una tabla que contiene airport_id y airline_id, es posible que tenga una interfaz;

public interface AirportDAO { public List<Airline> getAirlinesOperatingFrom(Set<Airport> airports); }

..y puede proporcionar una implementación de Hibernate de esto;

public class HibernateAirportDAO implements AirportDAO { public List<Airline> getAirlinesOperatingFrom(Set<Airport> airports) { //implementation here using EntityManager. } }

También podría considerar tener una Lista en su entidad de la Aerolínea y definir la relación con una anotación @ManyToMany JPA. Esto eliminaría la necesidad de tener este método DAO en particular por completo.

También puede consultar el patrón Abstract Factory para escribir fábricas DAO. Por ejemplo;

public abstract class DAOFactory { private static HibernateDAOFactory hdf = new HibernateDAOFactory(); public abstract AirportDAO getAirlineDAO(); public static DAOFactory getFactory() { //return a concrete implementation here, which implementation you //return might depend on some application configuration settings. } } public class HibernateDAOFactory extends DAOFactory { private static EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("myPersistenceUnit"); public static EntityManager getEM() { return emFactory.createEntityManager(); } public AirportDAO getAirportDAO() { return new HibernateAirportDAO(); } }

Este patrón le permite a su HibernateDAOFactory mantener un solo EMF y suministrar instancias DAO individuales con EMs. Si no desea pasar por la ruta de la fatiga, Spring es excelente para manejar las instancias de DAO con la inyección de dependencia.

Editar: aclaró un par de suposiciones.


Un DAO debe proporcionar acceso a una sola fuente de datos relacionada y, dependiendo de qué tan complicado sea su modelo de negocio, devolverá objetos comerciales completos o simples objetos de datos. De cualquier manera, los métodos DAO deben reflejar la base de datos de forma cercana.

Un Servicio puede proporcionar una interfaz de nivel superior no solo para procesar sus objetos comerciales, sino para tener acceso a ellos en primer lugar. Si obtengo un objeto comercial de un Servicio, ese objeto puede crearse a partir de diferentes bases de datos (y diferentes DAO), podría decorarse con información proveniente de una solicitud HTTP. Puede tener cierta lógica comercial que convierta varios objetos de datos en un único objeto comercial sólido.

Generalmente creo un DAO pensando que será utilizado por cualquiera que vaya a usar esa base de datos, o un conjunto de datos relacionados con el negocio, es literalmente el código de nivel más bajo además de desencadenantes, funciones y procedimientos almacenados dentro de la base de datos.

Respuestas a preguntas específicas:

Me preguntaba si un DAO podría contener métodos que realmente no tienen que hacer mucho con el acceso a los datos, pero que son mucho más fáciles de ejecutar con una consulta.

para la mayoría de los casos, no, le gustaría tener su lógica de negocios más complicada en su capa de servicio, el ensamblaje de datos de consultas separadas. Sin embargo, si le preocupa la velocidad de procesamiento, una capa de servicio puede delegar una acción en un DAO aunque rompa la belleza del modelo, de forma muy similar a como un programador de C ++ puede escribir código ensamblador para acelerar ciertas acciones.

Me parece que es más un método de capa de servicio, pero no estoy seguro de si el uso de JPA EntityManager en la capa de servicio es un ejemplo de buena práctica.

Si va a usar su administrador de entidades en su servicio, piense en el administrador de entidades como su DAO, porque eso es exactamente lo que es. Si necesita eliminar algún tipo de creación de consultas redundantes, no lo haga en su clase de servicio, extráigalo en una clase que utilice el administrador de entidades y haga de ese su DAO. Si su caso de uso es realmente simple, puede omitir la capa de servicio por completo y usar su administrador de entidades, o DAO en los controladores, porque todo su servicio va a hacer pasar las llamadas a getAirplaneById() al getAirplaneById() de DAO findAirplaneById()

ACTUALIZACIÓN: para aclarar con respecto a la discusión a continuación, el uso de un administrador de entidades en un servicio probablemente no sea la mejor decisión en la mayoría de las situaciones donde también hay una capa DAO por varias razones destacadas en los comentarios. Pero en mi opinión, sería perfectamente razonable dado:

  1. El servicio necesita interactuar con diferentes conjuntos de datos
  2. Al menos un conjunto de datos ya tiene un DAO
  3. La clase de servicio reside en un módulo que requiere cierta persistencia, lo suficientemente simple como para no garantizar su propio DAO

ejemplo.

//some system that contains all our customers information class PersonDao { findPersonBySSN( long ssn ) } //some other system where we store pets class PetDao { findPetsByAreaCode() findCatByFullName() } //some web portal your building has this service class OurPortalPetLostAndFoundService { notifyOfLocalLostPets( Person p ) { Location l = ourPortalEntityManager.findSingle( PortalUser.class, p.getSSN() ) .getOptions().getLocation(); ... use other DAO''s to get contact information and pets... } }


Una cosa es segura: si usa EntityManager en la capa de servicio, no necesita una capa de dao (solo una capa debe conocer los detalles de implementación). Aparte de eso, hay diferentes opiniones:

  • Algunos dicen que EntityManager expone toda la funcionalidad dao necesaria, por lo que inyectan EntityManager en la capa de servicio.
  • Otros tienen una capa dao tradicional respaldada por interfaces (por lo que la capa de servicio no está vinculada a los detalles de implementación).

El segundo enfoque es más elegante en lo que respecta a la separación de preocupaciones y también facilitará el cambio de una tecnología de persistencia a la otra (solo tiene que volver a implementar las interfaces de dao con la nueva tecnología), pero si sabe que nada cambiará, el primero es más fácil.

Yo diría que si tienes un proyecto pequeño, usa JPA en la capa de servicio, pero en un proyecto grande usa una capa DAO dedicada.