DAO vs ORM(休眠)模式[关闭]

问题描述 投票:43回答:3

我在一些文章中读到DAO对于hibernate并不是强制性的,它的实现是“依赖于”,换句话说,我们可以在ORM与DAO模式之间进行选择。

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

特别是对于“搜索”和“查找”查询来说,总是重写它们是不正确的,所以合理的想法就是把它们放到一个类中。

但是这个类是一个简单的DAO,没有DAO模式和DAOFactory的所有实现,只是DAO的轻量级实现。所以,重点是我们总是需要一个DAO,而选择是重DAO实现还是轻量级DAO实现?

我说的是错的?

编辑我的另一个问题是放置dao交互,例如我必须登录用户并写入登录日志(我知道无用的例子......)

所以在DAO模式中,我有所有泛型dao实现,DAOFactory,最后是UserHibernateDAO和LogHibernateDAO。登录操作是一种业务方法:

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

这合理吗?我可以用这种方式使用dao吗?如果我想要处理异常,那么更好的地方就是业务逻辑?

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

java hibernate design-patterns dao
3个回答
75
投票

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

也就是说,虽然你真的不需要任何东西,但你应该使用DAO。该模式适用于模块化代码。您将所有持久性逻辑保存在一个位置(分离关注点,对抗漏洞抽象)。您允许自己与应用程序的其余部分分开测试数据访问。并且您允许自己测试与数据访问隔离的应用程序的其余部分(即您可以模拟您的DAO)。

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

编辑 - 关于您的示例,您的登录方法应该在某种AuthenticationService中。您可以在那里处理异常(在登录方法中)。如果你使用Spring,它可以为你管理一堆东西:(1)事务,(2)依赖注入。您不需要编写自己的事务或dao工厂,只需定义服务方法的事务边界,并将DAO实现定义为bean,然后将它们连接到服务中。

Aaditi

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

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

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

毫无疑问,如果你不使用Spring或类似的东西,交易将是一个痛苦。我强烈建议使用Spring来管理您的事务,或者我认为您可以使用注释定义服务周围事务的EJB规范。

查看以下链接,了解基于容器的交易。

Container-Managed Transactions

Sessions And Transactions

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

另一种(不那么优雅)的替代方案是将所有原子单位放在DAO中。您可以使用CRUD DAO进行简单操作,然后使用更复杂的DAO执行多个CRUD操作。这样,您的程序化事务将保留在DAO中,您的服务将调用更复杂的DAO,而不必担心事务。

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

AO vs ORM(hibernate) pattern

(thanx @daff

请注意接口的定义如何使您的业务逻辑只关注UserDao的行为。它不关心实现。您可以使用hibernate或JDBC编写DAO。因此,您可以更改数据访问实施,而不会影响程序的其余部分。


30
投票

让我为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
    }
}

因此,如前所述,DAO是一种设计模式,用于最小化应用程序与后端之间的耦合,而ORM则处理如何将对象映射到对象关系数据库(这会减少数据库与应用程序之间的耦合,但最后,如果不使用DAO,您的应用程序将依赖于所使用的ORM或更高级别的标准(如JPA)。

因此,如果没有DAO,将很难更改您的应用程序(例如,转移到NoSQL数据库而不是JPA兼容的ORM)。


12
投票

不,我不认为这是正确的。 ORM是实现DAO的一种方式;你可以选择在没有ORM的情况下做DAO。

你已经倒退了:我认为ORM比DAO重,因为依赖性更大。我可以在没有ORM的情况下直接在JDBC中编写DAO。这比较轻,IMO。

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

© www.soinside.com 2019 - 2024. All rights reserved.