java - j2ee - Patrón DAO vs ORM(hibernación)
generic dao hibernate (3)
No, no creo que sea correcto. ORM es una forma de implementar DAO; puede elegir hacer DAO sin ORM.
Lo tienes al revés: consideraría que ORM es más pesado que DAO, porque las dependencias son mayores. Puedo escribir un DAO en JDBC directo sin ORM. Eso es más ligero, IMO.
Que estemos o no de acuerdo depende de cómo definamos "ligero" y "pesado". Estoy pasando por dependencias: la cantidad de JAR adicionales necesarios por encima del propio JDK.
He leído en algunos artículos que DAO no es obligatorio con hibernación y su implementación es por "depende", en otras palabras, podemos elegir entre ORM vs DAO patrón.
De acuerdo, supongamos que no quiero usar un patrón DAO, así que estoy usando solo la sesión CRUD y la operación de consulta proporcionada por hibernate (mi ORM).
Especialmente para las consultas de "búsqueda" y "búsqueda" no es correcto reescribirlas siempre, por lo que es razonable pensar en ponerlas en una clase.
Pero esta clase es un DAO simple sin toda la implementación del patrón DAO y DAOFactory, solo una implementación liviana de un DAO. Entonces, ¿el punto es que necesitamos siempre un DAO y la elección es una implementación de DAO pesada versus una implementación de DAO ligera?
Lo que dije es malo?
EDITAR Otro problema que tengo es dónde poner interacciones de dao, por ejemplo, tengo que iniciar sesión en un usuario y escribir un registro de inicio de sesión (ejemplo inútil, lo sé ...)
Entonces en un patrón DAO tengo todas las implementaciones genéricas de dao, una DAOFactory y finalmente UserHibernateDAO y LogHibernateDAO. La operación de inicio de sesión es un método comercial :
private void login(String username, String password){
daoFactory.beginTransaction();
UserDAO userDao=daoFactory.HIBERNATE.getUserDao();
LogDAO logDao=daoFactory.HIBERNATE.getLogDao();
if(userDao.checkAccount(username, password){
User user=userDao.findByAccount(username, password);
logDao.save(new Log("log-in", user);
}
daoFactory.commit();
}
Es esto razonable? ¿Puedo usar dao de esta manera? Si deseo manejar la excepción, ¿el mejor lugar para hacerlo es una lógica comercial?
EDIT2 Supongamos que usamos un patrón DAO, la razón principal para hacerlo es poder cambiar entre tecnología (ORM-> JDBC, etc.), todo está bien y está bien, PERO ¿dónde puedo manejar la sesión de hibernación y la transacción? No puedo ponerlo en un DAO, es un patrón anty, y no puedo ponerlo en una capa de servicio, porque en un conmutador hipohtetycal tengo que eliminar toda esta transacción (porque es posible que otros tecnologistas no los utilicen).
ORM y DAO son conceptos ortogonales. Uno tiene que ver con la forma en que los objetos se asignan a las tablas de la base de datos, el otro es un patrón de diseño para escribir objetos que acceden a los datos. No eliges ''entre'' ellos. Puede tener ORM y DAO es la misma aplicación, del mismo modo que no necesita ORM para usar el patrón DAO.
Dicho esto, aunque nunca necesitas nada, debes usar DAO. El patrón se presta a código modularizado. Mantiene toda su lógica de persistencia en un solo lugar (separación de preocupaciones, lucha contra las abstracciones con fugas). Se permite probar el acceso a los datos por separado del resto de la aplicación. Y se permite probar el resto de la aplicación aislada del acceso a datos (es decir, puede burlarse de sus DAO).
Además, seguir el patrón DAO es fácil, incluso si implementar el acceso a los datos puede ser difícil. Entonces te cuesta muy poco (o nada) y ganas mucho.
EDITAR - Con respecto a su ejemplo, su método de inicio de sesión debe estar en algún tipo de Servicio de autenticación. Puede manejar excepciones allí (en el método de inicio de sesión). Si usó Spring, podría administrar varias cosas para usted: (1) transacciones, (2) inyección de dependencia. No necesitaría escribir sus propias transacciones o fábricas dao, podría simplemente definir límites de transacciones en torno a sus métodos de servicio, y definir sus implementaciones DAO como beans y luego conectarlas a su servicio.
EDIT2
La razón principal para usar el patrón es separar las preocupaciones. Eso significa que todo su código de persistencia está en un solo lugar. Un efecto colateral de esto es la capacidad de prueba y mantenimiento, y el hecho de que esto hace que sea más fácil cambiar las implementaciones más tarde. Si está construyendo DAO basados en Hibernate, puede manipular absolutamente la sesión en el DAO, eso es lo que se supone que debe hacer. El patrón anti es cuando el código relacionado con la persistencia ocurre fuera de la capa de persistencia (ley de abstracciones con fugas).
Las transacciones son un poco más complicadas. A primera vista, las transacciones pueden parecer una preocupación de la persistencia, y lo son. Pero no son solo una preocupación de persistencia. Las transacciones también son una preocupación de sus servicios, ya que sus métodos de servicio deben definir una ''unidad de trabajo'', lo que significa que todo lo que sucede en un método de servicio debe ser atómico. Si usa transacciones de hibernación, entonces tendrá que escribir el código de transacción de hibernación fuera de sus DAO, para definir límites de transacción en torno a los servicios que utilizan muchos métodos DAO.
Pero tenga en cuenta que las transacciones pueden ser independientes de su implementación: necesita transacciones ya sea que use hibernate o no. También tenga en cuenta que no necesita utilizar el mecanismo de transacción de hibernación: puede usar transacciones basadas en contenedores, transacciones de JTA, etc.
Sin duda, si no usas Spring o algo similar, las transacciones van a ser un problema. Recomiendo utilizar Spring para administrar sus transacciones, o las especificaciones de EJB, donde creo que puede definir transacciones alrededor de sus servicios con anotaciones.
Consulte los siguientes enlaces para transacciones basadas en contenedores.
Transacciones gestionadas por contenedores
Lo que estoy recopilando de esto es que puede definir fácilmente las transacciones fuera de los DAO a nivel de servicio, y no necesita escribir ningún código de transacción.
Otra alternativa (menos elegante) es poner todas las unidades de trabajo atómicas dentro de los DAO. Podría tener DAO CRUD para las operaciones simples, y luego DAOs más complicados que realicen más de una operación CRUD. De esta forma, sus transacciones programáticas permanecen en el DAO, y sus servicios llamarían a los DAO más complicados y no tendrían que preocuparse por las transacciones.
El siguiente enlace es un buen ejemplo de cómo el patrón DAO puede ayudarlo a simplificar el código
Patrón AO vs ORM (hibernación)
(gracias @ daff )
Observe cómo la definición de la interfaz lo hace para que su lógica empresarial solo se preocupe por el comportamiento de UserDao. No le importa la implementación. Puede escribir un DAO usando hibernación, o solo JDBC. Entonces puede cambiar su implementación de acceso a datos sin afectar el resto de su programa.
Permítanme proporcionar un ejemplo de código fuente a la buena respuesta de hvgotcodes:
public class Application
{
private UserDao userDao;
public Application(UserDao dao)
{
// Get the actual implementation
// e.g. through dependency injection
this.userDao = dao;
}
public void login()
{
// No matter from where
User = userDao.findByUsername("Dummy");
}
}
public interface UserDao
{
User findByUsername(String name);
}
public class HibernateUserDao implements UserDao
{
public User findByUsername(String name)
{
// Do some Hibernate specific stuff
this.session.createQuery...
}
}
public class SqlUserDao implements UserDao
{
public User findByUsername(String name)
{
String query = "SELECT * FROM users WHERE name = ''" + name + "''";
// Execute SQL query and do mapping to the object
}
}
public class LdapUserDao implements UserDao
{
public User findByUsername(String name)
{
// Get this from LDAP directory
}
}
public class NoSqlUserDao implements UserDao
{
public User findByUsername(String name)
{
// Do something with e.g. couchdb
ViewResults resultAdHoc = db.adhoc("function (doc) { if (doc.name==''" + name + "'') { return doc; }}");
// Map the result document to user
}
}
Entonces, como ya se mencionó, DAO es un patrón de diseño para minimizar el acoplamiento entre su aplicación y su backend, mientras que ORM trata de cómo mapear objetos en una base de datos relacional de objetos (que reduce el acoplamiento entre la base de datos y su aplicación, pero al final sin usar un DAO, su aplicación dependería del ORM utilizado o en un nivel superior, un estándar como JPA).
Por lo tanto, sin DAO, sería muy difícil cambiar su aplicación (por ejemplo, cambiar a una base de datos NoSQL en lugar de un ORM compatible con JPA).