Esto es lo que creo que es el punto de vista tradicional:
- Las entidades en su proyecto forman el modelo de dominio. Deben ser reutilizables y no estar estrechamente conectados a una tecnología de persistencia (volveré más adelante sobre el acoplamiento apretado vs. libre)
- La capa de negocios, usa el modelo de dominio, pero también expone servicios y otras cosas.
- La capa de acceso a datos se encarga de mantener el modelo de dominio (entidades) en una tienda persistente.
Una entidad no debe llamar a la capa de acceso a datos directamente. Pero la capa de negocios, de alguna manera, cargará y persistirá entidades del modelo de dominio.
Si asigna a que las tecnologías Java EE que se suele sentir algo como:
- Entidades -> POJO con anotaciones de Hibernate/JPA. Tenga en cuenta que las anotaciones no implican un acoplamiento estrecho con JPA/Hibernate, el mismo POJO podría usarse en otro lugar sin Hibernate.
- capa de negocios -> EJB de sesión o primavera
- capa de acceso de datos -> JPA/Hibernate
Eso es un esbozo y hay una gran cantidad de variantes posibles. En particular, puede omitir el EJB de sesión e implementar la capa empresarial de otra manera. También puede decidir que la capa empresarial llame directamente a la sesión JPA/Hibernate/EntityManager, en cuyo caso JPA/Hibernate es realmente el DAL, o puede desear ajustar el acceso a Session/EntityManager en los llamados Objetos de acceso a datos (DAO)
En cuanto a HQL, trate de atenerse a lo que es portátil, y si utiliza SQL nativo, siga las convenciones de SQL-92. Si las cosas se complican, tal vez introduzca DAO. De esta forma, usted sabe que el único lugar donde hay consultas HQL es en los DAO. También puede implementar primero la lógica de consulta "procedurally" en el DAO, y si tiene un problema de rendimiento, vuelva a implementarlo con una consulta HQL más complicada.
EDITAR
En cuanto a sus preguntas en el comentario:
La capa de negocio depende de la capa de datos. Si desea que la capa empresarial no dependa de Hibernate/JPA, entonces su capa de datos necesita abstract Hibernate/JPA de distancia. Si usa DAO para su capa de datos, ese será el caso. El DAO será la "fina capa de persistencia escrita a mano sobre Hibernate" (para tomar sus palabras). Presentaría DAO para todas las entidades en su caso.
Lo que estás preguntando es una pregunta de diseño bastante genérica. No puedo dar una receta definitiva para eso, ni tampoco puedo resumir todas las variantes en una respuesta, ya que depende de cada caso. Por ejemplo, no hablamos tanto sobre el problema de las transacciones, que normalmente comienza en la capa de negocios, pero que la capa de datos debe tener en cuenta. Esto generalmente depende de las tecnologías utilizadas y sus requisitos.
Sin embargo, aquí hay una lista de los recursos que le pueden interesar: los libros Pattern of Enterprise Application Architecture, el libro Real World Java EE Patterns - Rethinking Best Practices, el libro Domain Driven Design y más específicamente los patrones Data Access Object, Repository pattern, Open Session in View (si es para una aplicación web), y tal vez Anemic Domain Model.
EDIT 2
Ok, un poco más frases sobre transacciones:
Transacciones conceptualmente deben gestionarse de la capa de negocio; la definición de lo que debe hacerse en una unidad de trabajo para ser coherente depende, de hecho, de la propia lógica de la aplicación.
Con EJB3, las transacciones se pueden declarar con anotaciones y la aplicación. el servidor lo hace por ti. Ver this other answer mío para más información. Con Spring también puede marcar las transacciones de forma declarativa, pero no sé los detalles. De lo contrario, tendrá que iniciar/detener la transacción usted mismo.Esto será ligeramente diferente si usa transacciones JDBC o transacciones JTA.
Las transacciones también se relacionan con la carga diferida en Hibernate/JPA. Una entidad que se cargó de forma diferida, de hecho, solo se puede cargar si hay una transacción actual. Si las transacciones finalizan en la capa empresarial, las entidades que se devuelven a la capa de presentación deben cargarse con entusiasmo.
Para evitar este problema, un patrón popular para aplicaciones web es Open Session in View, que ya he mencionado. En este caso, la capa de presentación inicia/detiene las transacciones (lo cual es un poco erróneo conceptualmente), pero funciona bien con la carga diferida.
Estoy totalmente de acuerdo, y eventualmente recomendaría usar JPQL en lugar de HQL para cumplir con los estándares. – snowflake
Puedo estar equivocado sobre la terminología aquí. Cuando dije 'modelado de dominio', me refería a la tríada M de MVC, que en esencia es la 'aplicación central' (incluida la capa empresarial), algo que potencialmente podría conducir a través de una interfaz de línea de comando (reescribiendo la V y la C para la CLI)! Ahora, una de las cosas que hará esta M es la persistencia. Para esto, la M necesita estar libre de cualquier cosa de persistencia específica del proveedor. Por lo tanto, la necesidad de una fina (o, gruesa/sofisticada) capa de persistencia escrita a mano sobre Hibernate. ¿Podrías corregirme si me equivoco aquí? – Harry
"Si las cosas se complican, tal vez introduzca DAO". Quiere decir, caso por caso (suponiendo, por supuesto, que DAO y HQL/JPQL coexistan pacíficamente). Realmente me gustaría poder diseñar mis objetos de tal manera que HQL sea suficiente (debido al poder del paradigma relacional), y para consultas realmente complicadas, escribo código imperativo. – Harry