在我的Spring MVC应用程序中,我在表示层中使用DTO,以便将域模型封装在服务层中。 DTO被用作弹簧形式的背衬物体。
因此我的服务看起来像这样:
userService.storeUser(NewUserRequestDTO req);
服务层将翻译DTO - >域对象并完成剩下的工作。
现在我的问题是,当我想从服务中检索DTO来执行更新或显示我似乎找不到更好的方法来执行它然后有多个方法用于返回不同DTO的查找像...
EditUserRequestDTO userService.loadUserForEdit(int id);
DisplayUserDTO userService.loadUserForDisplay(int id);
但是这种方法感觉不对。也许服务不应该返回像EditUserRequestDTO这样的东西,控制器应该负责从专用表单对象组装requestDTO,反之亦然。
确实有单独的DTO的原因是DisplayUserDTO被强类型化为只读,并且用户的许多属性是db中查找表中的实体(如城市和州),因此DisplayUserDTO将具有字符串EditUserRequestDTO将具有将支持表单中的选择下拉列表的id的属性描述。
您怎么看?
感谢
答案 0 :(得分:2)
我喜欢精简的显示对象。它比构建整个域对象只是为了显示它的几个字段更有效。我使用了类似的模式,但有一点不同。我只使用了视图中的域对象,而不是使用DTO的编辑版本。它显着减少了在对象之间来回复制数据的工作。我现在还没有决定是否要这样做,因为我正在使用JPA和Bean Validation Framework的注释,并且混合注释看起来很混乱。但我并不喜欢使用DTO只是为了将域对象保留在MVC层之外。似乎很多工作没有太大的好处。另外,阅读福勒对anemic objects的看法可能会有所帮助。它可能不完全适用,但值得考虑。
第一编辑:回复以下评论。
是的,我喜欢为一次操作单个对象的所有页面使用实际的域对象:编辑,查看,创建等。
您说您正在获取现有对象并将您需要的字段复制到DTO中,然后将DTO作为模型的一部分传递给视图页面的模板引擎(反之亦然,用于创建)。这会给你带来什么?对DTO的引用的权重不小于对完整域对象的引用,并且您还要进行所有额外的属性复制。没有规则说你的模板引擎必须使用你对象的每个方法。
我会使用一个小的部分域对象,如果它提高了效率(没有建立关系图),特别是对于搜索结果。但是,如果对象已经存在,那么当您将其粘贴到模型中以呈现页面时,不要担心它的大小或复杂程度。它不会在内存中移动对象。它不会引起模板发动机的压力。它只是访问它需要的方法而忽略了其余的方法。
第二次编辑: 好点子。在某些情况下,您可能希望视图可用的有限属性集(即,不同的前端和后端开发人员)。在回答之前我应该仔细阅读。如果我打算做你想做的事情,我可能会在表单forEdit()和forDisplay()的用户(或任何类)上放置单独的方法。这样你就可以从服务层获取用户并告诉用户使用自己的有限副本。我想也许这就是我用贫血物体评论所达到的目标。
答案 1 :(得分:2)
你应该使用DTO而不是MVC层中的ORM!已经就此问题提出了许多非常好的问题,例如:Why should I isolate my domain entities from my presentation layer?
但是要添加到该问题,您应该将它们分开以帮助防止ORM被绑定在帖子上,因为有可能有人添加额外的字段并导致各种混乱需要不必要的额外验证。