【问题标题】:controllers, entity classes or dao - what goes where?控制器、实体类或 dao - 什么去哪里?
【发布时间】:2011-10-04 15:50:44
【问题描述】:

随着在我的项目中引入 Hibernate,我的代码开始变得真正耦合,并且在许多地方都出现了样板(应该反过来,对吧?)

我被一个特定的例子弄糊涂了。我一直认为 DAO 对象本质上是非常通用的(主要封装了基本的 CRUD 操作以及后端存储实现)

不幸的是,随着我的实体类开始变得越来越复杂,我开始将越来越多的逻辑卸载到 DAO 对象中。我有一个特别的例子:

我的实体类User应该有一个叫做friends的关系,它本质上是一个用户的集合。但是,我必须将我的类映射到 UserFriendship 对象的集合,每个对象都包含对朋友对象的引用,还包含其他特定的友谊数据(友谊发生的日期)

现在,很容易在实体类中引入自定义 getter,它将获取 UserFriendship 对象的集合并将其转换为 User 对象的集合。但是,如果我只需要我的朋友集合的一个子集,比如在分页中,该怎么办。我不能在实体对象中真正做到这一点,因为它无权访问会话,对吗?这也适用于我需要对关系进行参数化查询时。有权访问会话的是 UserDAO。所以我最终得到了这个

用户DAO => 普通的 CRUD 方法 => getFriends(整数偏移量,整数限制); => 一堆类似的 getter 和 setter,负责管理 User 实例中的关系。

这太疯狂了。但我真的无能为力。我不知道是否可以在实体类中声明计算属性,也可以对其进行参数化。

从技术上讲,我也可以将 DAO 包装在实体中,并将​​帮助器 getter 和 setter 放回实体类中,它们应该在哪里,但我不确定这是否也是一个好习惯。

我知道DAO应该只能被控制器对象访问,它应该提供一个或多或少完整的实体对象或一组实体对象。

我很困惑。我的所有 DAO 对象或多或少现在都耦合了应该在实体对象或控制器中的逻辑。

如果我的问题有点令人困惑,我很抱歉。表述起来有点困难。

【问题讨论】:

  • 有效问题 - 但是为了获得更好的答案,我会将您的问题总结为最后的简单 1-2 句要点。
  • 要添加到您的列表中的一件事是服务。我们的 DAO 执行简单的数据库操作,并且不包含太多(如果有的话)逻辑。我们的实体只是数据持有者。控制器中包含业务逻辑,但通常它们只是构建模型并选择视图。如果我们需要对数据库中的实体进行逻辑处理(过滤、缓存等),那么我们就有了一个服务层。
  • 您会将以下方法 getFriends(Criterion criteria) 和 getPhotos(Criterion criteria) 放在哪里?我会说他们应该留在 User 实体实例中。否则,将它们放入 DAO 和服务中不是破坏 OOP 模型吗?
  • 我的意思是,我发现调用 PhotoDAO 并查询属于给定用户的照片,而不是获取用户实例,然后简单地调用 getPhotos(...)

标签: java hibernate orm dao


【解决方案1】:

我的一般规则是:

  • 在实体类中,尊重law of Demeter:不要和陌生人说话
  • 实体类不得使用会话
  • 控制器/服务类不得使用会话。他们可以在实体图中导航并调用 DAO 方法
  • DAO 方法应该是使用会话的方法。他们的工作包括获取、保存、合并实体和执行查询。如果应该为单个用例执行多个查询或与持久性相关的操作,则控制器/服务应该协调它们,而不是 DAO。

这样,我可以通过 mock DAO 相对轻松地测试业务逻辑,并且我可以相对轻松地测试 DAO,因为它们不包含太多逻辑。大多数测试验证查询是否找到了他们应该找到的内容,以适当的顺序返回它们,并初始化必须初始化的关联(以避免在表示层中出现延迟加载异常,我正在使用分离的对象)

【讨论】:

  • 对于一个简单的答案,user802232 必须有一个更复杂的 DAO,其中包含一些特定的查询或每个实体的获取策略,对吗?
猜你喜欢
  • 1970-01-01
  • 2010-09-08
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多