java DAO与ORM(休眠)模式[已关闭]

wsxa1bj1  于 2022-12-28  发布在  Java
关注(0)|答案(3)|浏览(116)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新此问题,以便editing this post可以用事实和引文来回答。

九年前就关门了。
Improve this question
我在一些文章中读到DAO并不是Hibernate所必需的,它的实现是通过“它依赖于”,换句话说,我们可以在ORM和DAO模式之间进行选择。
好,假设我不想使用DAO模式,所以我只使用Hibernate(我的ORM)提供的会话CRUD和查询操作。
特别是对于“search”和“find”查询总是不正确地重写它们,所以合理的想法是把它们放到一个类中。
但是这个类是一个简单的DAO,没有DAO模式和DAOFactory的所有实现,只有一个DAO的轻量级实现,那么,关键是我们总是需要一个DAO,是选择重型DAO实现还是轻量级DAO实现?
我说错了吗?

EDIT我的另一个问题是把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吗?如果我想处理异常,最好是在业务逻辑中处理。

EDIT 2让我们假设使用DAO模式,这样做的主要原因是能够在技术之间切换(ORM-〉JDBC等),一切都很好,但是我在哪里可以处理Hibernate会话和事务呢?我不能把它放在DAO中,这是一个很大的模式,我不能把它放在服务层中,因为在一个hipohtecal交换机中,我必须删除所有这些事务(因为其他技术可能不使用它们)。

gblwokeq

gblwokeq1#

ORM和DAO是两个相互垂直的概念。一个是关于对象如何Map到数据库表,另一个是用于编写访问数据的对象的设计模式。你不能在它们之间做出选择。你可以将ORM和DAO作为同一个应用程序,就像你不需要ORM来使用DAO模式一样。
也就是说,虽然你从来没有真正"需要"任何东西,但你应该使用DAO。这种模式适合于模块化代码。你把所有的持久性逻辑放在一个地方(分离关注点,对抗泄漏的抽象)。你允许自己独立于应用程序的其余部分测试数据访问。你允许自己独立于数据访问测试应用程序的其余部分(也就是说,你可以模拟你的DAO)。
另外,即使实现数据访问可能很困难,遵循DAO模式也很容易,因此成本很低(或者没有成本),但收益很大。

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

使用该模式的主要原因是分离关注点。这意味着您所有的持久性代码都在一个地方。这样做的副作用是可测试性和可维护性,而且事实上这使得以后切换实现更容易。如果您正在构建基于Hibernate的DAO,您完全可以在DAO中操作会话。这就是你应该做的。2反模式是当持久化相关的代码发生在持久化层之外的时候(泄漏抽象法则)。
事务有点棘手。乍一看,事务似乎是持久性的一个问题,事实也确实如此。但它们不仅仅是持久性的一个问题。事务也是你的服务的一个问题,因为你的服务方法应该定义一个"工作单元",这意味着,在一个服务方法中发生的每件事都应该是原子的。如果你使用Hibernate事务,那么你将不得不在你的DAO之外编写休眠事务代码,来定义使用许多DAO方法的服务周围的事务边界。
但是要注意,事务可以独立于您的实现--无论您是否使用Hibernate,您都需要事务。还要注意,您不需要使用Hibernate事务机制--您可以使用基于容器的事务、JTA事务等。
毫无疑问,如果你不使用Spring或类似的东西,事务将是一个痛苦。我强烈推荐使用Spring来管理你的事务,或者EJB规范,我相信你可以用注解来定义你的服务周围的事务。
查看以下链接,了解基于容器的事务。
Container-Managed Transactions
Sessions And Transactions
我从中得到的结论是,您可以很容易地在服务级别定义DAO之外的事务,并且不需要编写任何事务代码。
另一个(不太优雅的)选择是将所有原子工作单元放在DAO中。你可以使用CRUD DAO来执行简单的操作,然后使用更复杂的DAO来执行多个CRUD操作。这样,你的编程事务就留在DAO中,你的服务将调用更复杂的DAO,而不必担心事务。
下面的链接是DAO模式如何帮助您简化代码的一个很好的示例
AO与ORM(休眠)模式
(谢谢)
请注意接口的定义是如何使业务逻辑只关心UserDao的行为,而不关心实现的。您可以使用hib或JDBC编写DAO。因此,您可以更改数据访问实现,而不会影响程序的其余部分。

toe95027

toe950272#

让我提供一个源代码的例子,以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处理如何将对象Map到对象关系数据库(这减少了数据库和应用程序之间的耦合,但最终,如果不使用DAO,应用程序将依赖于所使用的ORM或更高级别的标准,如JPA)。
因此,如果没有DAO,更改应用程序将非常困难(例如,迁移到NoSQL数据库,而不是JPA兼容的ORM)。

raogr8fs

raogr8fs3#

不,我不认为这是正确的。ORM是实现DAO的一种方式;您可以选择不使用ORM来执行DAO。
你说反了:我认为ORM比DAO重,因为依赖性更大。我可以直接用JDBC编写DAO而不用ORM。这样更轻,IMO。
我们是否同意取决于我们如何定义“轻”和“重”,我将根据依赖性--JDK本身之外所需的额外JAR的数量来定义。

相关问题