将DTO传递到服务层

13

将DTO对象传递到服务层不是一个不好的做法吗?

目前我的服务层方法看起来像这样:

public save(MyEntity entity);

将DTO中的值映射到业务实体(MyEntity)上是在表示层完成的。

但我想将方法签名更改为:

public save(MyEntityDTO dto, String author);

然后在服务层将进行从DTO到业务实体对象的映射。

EDIT: 我这样做是因为在从DTO到业务对象的映射时需要开放Hibernate会话,这样所有对实体的更改都将自动刷新。


这并不是犯罪,一切取决于情况。阅读一些关于软件分层架构的文章可能会有所帮助。 - Imran Rizvi
3个回答

18
将DTO对象传递到服务层不是不好的实践。你不仅可以传递DTO对象到服务层,而且应该将DTO对象传递给服务层。您的服务应该接收DTO,将它们映射到业务实体并将其发送到存储库。它还应从存储库检索业务实体,将它们映射到DTO并将DTO作为响应返回。因此,您的业务实体从未离开业务层,只有DTO离开。
参考这里获取类似问题的完整答案。

这就是我一直以来的想法。然而,在某些在线示例中(特别是在REST API服务器的情况下),服务层接受DTO,但返回模型,我觉得这相当令人困扰(例如:Client add(ClientDTO client))。你有什么想法吗?谢谢! - ChambreNoire
1
我知道我有点晚了,但如果我从另一个服务调用服务怎么办? - Morgan
7
错误的答案。底层不应该知道架构顶部的层。它们应该有自己的API,以提供在层内部彼此通信的能力。对于服务之间的通信,您将仅使用服务层对象,而不需要映射到控制器(客户端)级别的DTO。对于控制器和服务之间的通信,您需要进行一些基本验证和映射到服务层对象,然后调用实际的服务方法。 - user3435425
9
这个答案是非常错误的,它展示了SO可能会误导人们,不能被视为无论如何和在所有情况下都是唯一有效的开发者资源。它是错误的。服务层不应该关心您的数据传输对象(DTOs),它是业务层,只应处理业务逻辑。在控制器中,您应该处理DTOs。 - Mejmo
1
然而,也许定义一下你的DTO对象是明智的。对我来说,它是一个在表现层上的对象,因此是REST控制器。想象一下,如果你在REST层中更改了某些内容...为什么我还要更改服务/业务层呢?业务逻辑有所改变吗?不,可能只是实体->DTO映射的更改,并且该映射是在控制器中完成的。 - Mejmo
@user3435425,回答的作者拥有34k的声望,在stackoverflow上我看到类似的答案,例如https://dev59.com/6lYN5IYBdhLWcg3wLFiI#67625653。 - parsecer

5
这是有争议的。 (如接受答案的评论所示) 一方面,DTO属于处理数据传输的应用程序层,显然是您的表示层。
另一方面,您的域对象(业务实体),在服务层中得到适当处理,可能具有其中的属性 - 比如说一个Id,一个LastUpdated或者其他不会被传递到save方法中的属性。那么你要传什么呢?好吧,你只传需要的属性。而且恰巧的是,请求MyEntityDTO保存()将恰好封装所有这些属性!...
所以现在你面临着不幸的选择:
1.从表示层传递业务对象 (也破坏了分层模型,并迫使您忽略诸如Id和LastUpdated之类的属性,这些属性不在“请求”中)
2.将DTO分解为属性并传递它们: service.save(Dto.Property_One, Dto.Property_Two) 然后你必须在save()方法中重新组合它们。
3.创建一些新对象来封装Property_One,Property_Two等
4.承认DTO也是层间传输的
在我看来,没有一个是理想的选择,这就是为什么我认为#4是可以的。最正确的可能是#2 - 但同样...并不理想。
有时候命名可以缓解痛苦:“MyEntityRequest”而不是“DTO”

如果服务层返回实体,我想我们在事务方面可能会遇到另一个问题。如果服务返回的实体具有一些延迟加载集合,我们应该在控制器中打开事务以访问数据,对吗?从控制器打开事务可以吗? - Al Xx

0

没问题,所有标准的三层架构都是这样做的。数据访问获取数据,业务层映射和操作数据,表示层呈现数据。将数据访问模型传递给表示层是不好的,但是并没有犯罪——到这一点,您应该传递业务模型。顺便说一下,“DTO”可以指任何东西,业务层模型可以是DTO,数据访问模型也可以是DTO。DTO通常是C#中的POCO。通常您有数据访问模型,代表数据库实体和领域模型,它们在应用程序中传递数据。领域模型通常是DTO(或称为POCO)。这意味着,在Microsoft语言中,它们是完全可序列化的,因此您可以将它们传递给任何Microsoft .NET组件。您还可以将它们序列化为XML、JSON等等...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接