DAO与ORM(hibernate)模式

我读过一些文章,DAO不是强制性的,它的实现是由“它依赖”,换句话说,我们可以在ORM和DAO模式之间进行select。

好吧,让我们假设我不想使用DAO模式,所以我只使用会话CRUD和由hibernate(my ORM)提供的查询操作。

特别是对于“search”和“查找”查询是不正确的,总是要重写它们,所以合理的考虑把它们放到一个类中。

但是这个类是一个简单的DAO,没有全部实现DAO模式和DAOFactory,只是一个轻量级的DAO实现。 所以,重点是我们需要一个DAO,并且select重DAO实现还是轻量级DAO实现?

我说的是错的?

编辑我有另一个问题是把道相互作用,例如我必须login一个用户,并写入login日志(无用的例子,我知道…)

所以在一个DAO模式中,我有所有通用的dao实现,一个DAOFactory,最后是UserHibernateDAO和LogHibernateDAO。 login操作是一种业务方法

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(); } 

这是合理的吗? 我可以用这种方式使用道? 如果我想处理exception,更好的地方是在一个业务逻辑?

EDIT2让我们假设使用DAO模式,这样做的主要原因是能够在技术(ORM-> JDBC等)之间切换,它一切正常,但我在哪里可以处理hibernate会话和事务? 我不能把它放进一个DAO,它是anty模式,我不能把它放到一个服务层,因为在一个hipohtetycal开关我不得不删除所有这个交易(因为其他技术可能不会使用它们)。

ORM和DAO是正交的概念。 一个是如何将对象映射到数据库表,另一个是用于编写访问数据的对象的devise模式。 你不要select“之间”。 你可以让ORM和DAO是同一个应用程序,就像你不需要ORM来使用DAO模式一样。

这就是说,虽然你从来没有真正需要任何东西,你应该使用DAO。 该模式适用于模块化代码。 你把所有的持久性逻辑放在一个地方(分离关注点,打击抽象的漏洞)。 您允许自己与应用程序的其余部分分开testing数据访问。 而且你允许自己testing从数据访问隔离的应用程序的其余部分(即你可以模拟你的DAO)。

另外,遵循DAO模式很容易,即使实施数据访问也很困难。 所以它花费你很less(或者没有),并且你获得了很多。

编辑 –就你的例子来说,你的login方法应该在某种AuthenticationService中。 您可以在那里处理exception(在login方法中)。 如果你使用Spring,它可以为你pipe理一堆东西:(1)事务,(2)dependency injection。 您不需要编写自己的事务或dao工厂,只需定义服务方法的事务边界,然后将DAO实现定义为bean,然后将它们连接到您的服务中。

EDIT2

使用该模式的主要原因是分开关注点。 这意味着所有的持久性代码都在一个地方。 这样做的一个副作用是可testing性和可维护性,以及事实上,这使得稍后切换实现变得更容易。 如果你正在构build基于Hibernate的DAO,你绝对可以在DAO中操作会话,这就是你应该做的。 反模式是持久层相关代码发生在持久层之外(泄漏抽象定律)。

交易有点棘手。 乍一看,交易可能似乎是一个持久性的关注,他们是。 但他们不仅是持久的关切。 交易也是你服务的关注点,因为你的服务方法应该定义一个“工作单元”,这意味着服务方法中发生的一切都应该是primefaces的。 如果你使用hibernate事务,那么你将不得不在你的DAO之外编写hibernate事务代码,来定义使用许多DAO方法的服务的事务边界。

但请注意,事务可以独立于您的实现 – 无论您是否使用hibernate,您都需要事务。 另外请注意,您不需要使用hibernate事务机制 – 您可以使用基于容器的事务,JTA事务等。

毫无疑问,如果你不使用Spring或类似的东西,交易将是一个痛苦。 我强烈build议使用Spring来pipe理您的事务,或者我相信您可以使用注释来定义与服务有关的事务的EJB规范。

查看以下链接,了解基于容器的事务。

容器pipe理事务

会话和事务

我从中收集的是,您可以轻松地在服务级别定义DAO之外的事务,而且您不需要编写任何事务代码。

另一个(较不优雅的)select是把所有的primefaces单位都放在DAO中。 对于简单操作,您可以有CRUD DAO,然后执行多个CRUD操作的更复杂的DAO。 这样,您的程序化交易将停留在DAO中,您的服务将调用更复杂的DAO,而不必担心事务。

以下链接是DAO模式如何帮助您简化代码的一个很好的例子

AO与ORM(hibernate)模式

(thanx @ daff )

请注意interace的定义如何使您的业务逻辑只关心UserDao的行为。 它并不关心实施。 你可以使用hibernate编写一个DAO,或者只是使用jdbc。 所以你可以改变你的数据访问实现而不影响你的程序的其余部分。

让我提供一个源代码的例子给hvgotcodes很好的答案:

 public class Application { private UserDao userDao; public Application(UserDao dao) { // Get the actual implementation // eg 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 eg couchdb ViewResults resultAdHoc = db.adhoc("function (doc) { if (doc.name=='" + name + "') { return doc; }}"); // Map the result document to user } } 

所以,如前所述,DAO是一种devise模式,可以最大程度地减less应用程序和后端之间的耦合,而ORM则处理如何将对象映射到对象关系数据库(这会减less数据库与应用程序之间的耦合,但最终,不使用DAO,您的应用程序将依赖于所使用的ORM或更高级别的JPA标准)。

因此,如果没有DAO,那么改变你的应用程序是非常困难的(例如转向NoSQL数据库,而不是JPA兼容的ORM)。

不,我不认为这是正确的。 ORM是实现DAO的一种方式; 你可以select不使用ORM来做DAO。

你已经倒过来了:我认为ORM比DAO更重,因为依赖关系更大。 我可以在没有ORM的直接JDBC中编写一个DAO。 IMO更轻。

我们是否同意取决于我们如何定义“轻”和“重”。 我将依赖关系 – JDK本身之上所需的额外JAR的数量。