ORM 和 DAO - 设计问题

Posted

技术标签:

【中文标题】ORM 和 DAO - 设计问题【英文标题】:ORM and DAO - design question 【发布时间】:2011-10-23 02:39:52 【问题描述】:

我目前正在开展这个讨论的项目,我想问问其他人对此有何看法。

DAO 模式是(根据***):“在计算机软件中,数据访问对象 (DAO) 是为某种类型的数据库或持久性机制提供抽象接口的对象,提供一些特定操作而不暴露数据库。”。

但是,使用 ORM 这显然是一个 ORM(例如 Hibernate)工作。它为某些(几乎所有)类型的数据库提供了一个抽象接口。

回顾最近的几个项目,让我们看看 DAO 层。第一步始终是带有 save()、findById()、findAll() 方法的通用 hibernate dao。这对我来说只是代理休眠会话方法。

更进一步,我看到了像这里提出的这样的接口:Generic DAO pattern in Hibernate,它完全将 DAO 严格限制为休眠的持久性方式(合并、标准查询)。除了 Hibernate 之外,此 DAO 不能与其他持久性机制一起使用。

所以最后一个问题是:对于这种常见的 DAO 设计,DAO 模式带来了什么新的东西?如果我想切换数据库引擎,我将它切换到休眠级别。那么,目前在 ORM 应用程序中使用 DAO 模式真的有什么好处吗?

让我们收集一些经验:

    您曾多少次看到 DAO 类层次结构与 Hibernate(或其他 ORM)紧密绑定,您认为这样做的好处是什么? 您在多少个项目中改变了持久性机制,以从 DAO 层获得好处(即您需要实现其他 DAO 层,因为您的工作无法通过切换 db 方言在 ORM 级别完成)?李> 在多少个项目中,您刚刚开发了大型 DAO 结构(每个域对象的接口+类)并且从未真正使用过(即,您从未更改基本 DAO 层次结构的实现)? 那么,您如何看待没有 DAO 层的应用程序,只使用 ORM 会话提供的抽象?

请分享经验。

【问题讨论】:

【参考方案1】:

恕我直言,DAO 模式在使用 ORM 时并不是真正关于切换数据库引擎的能力。这是关于

职责分离:业务逻辑到服务层,持久化到DAO层 能够通过模拟 DAO 层来测试服务层 能够测试持久性逻辑,因为它没有隐藏在业务逻辑中

我通常不希望每个域对象都有一个 DAO,而是每个功能用例集都有一个 DAO。事实上,我发现在一个足够复杂的应用程序中,大多数查询都没有链接到特定的域对象,而是链接到一个用例或一组用例。但是 YMMV,结合这两种方法有时很有用。

所以,回答您的具体问题:

    几乎总是这样。大多数情况下,使用 Hibernate 或 JPA 使用 DAO 与使用普通 JDBC 使用 DAO 不同 从不。通常,数据库的选择在项目开始之前很久就完成了,并且永远不会改变。 我倾向于只在需要时才开发 DAO,而不是因为存在域对象。但是拥有一个“通用 DAO”基类有时很方便 我认为它们更难测试,通常结构不完善,并且最终会一遍又一遍地重新实现相同的查询/加载,因为它们没有在可重用的 DAO 中隔离

【讨论】:

感谢您的回复。那么,我还有一个问题: 1. 不能在服务层模拟和测试,在默认实现中直接使用Session抽象吗? 2. “每个用例的 DAO”到底是什么意思?这对我来说是新的,因为我也在使用这种模式,但是在服务层上,我知道这种方法的另一个问题是在某处收集访问数据的方法——复杂的、可重复的查询。这可能是在 DAO 层上默认完成的,但通常这是在服务层上重复的,它们只是这些 DAO 的代理(从我看没有太多好处)。 1.不,因为会话方法太粗粒度,而且不够具体。模拟(和验证)dao.findFoosByField(String) 比 session.createQuery(String) 后跟 query.setMaxResults() 后跟 query.list() 更容易。 2. 例如,我可能有一个用于授权管理的 DAO,它将处理用户、角色、配置文件的持久性,而不是一个 DAO 用于用户,一个用于角色,另一个用于配置文件。 好的,我明白了。我使用 DB 人口进行测试而不是模拟,所以模拟 DAO 并没有真正帮助我。我在这里看到的 DAO 的另一个问题是限制/排序问题。结果需要很多方法和这些参数,而这一切都已经暴露了一层,界面非常方便。我真的很接近转向不同的解决方案。 你不是真正的单元测试,你的测试比必要的要长得多。模拟有助于测试业务逻辑而无需维护数据集,使测试运行得非常快,并且真正有助于测试极端情况。 我对这种方法有点了解,但我很难相信这一点。我的应用程序通常做的事情是从 db 获取数据,处理它们并再次将一些东西放入 db。那么对我来说,这更接近真实情况,在 db 上测试它(顺便测试与持久性相关的东西,比如关系等)。对不起,我的不符合规范,我最近在我的办公桌上用完全不同的方法编写了两个中等规模的项目,我在那里看到,classis 应用程序有 100-150% 的代码(并且需要工作时间),完全没有任何理由- 这让我想到了这个;)

以上是关于ORM 和 DAO - 设计问题的主要内容,如果未能解决你的问题,请参考以下文章

DAO设计和数据结构

mybatis关于ORM的使用以及设计[DaoInterface 转换 Mapper代理对象]

Android数据库设计——1,面向对象(ORM)建库建表

Android数据库设计——1,面向对象(ORM)建库建表

spring入门一:框架整体简介

工厂设计模式和DAO设计模式有啥区别