使用DTO的意义何在?它是过时的概念吗?我在视图层中使用POJO来传输和保留数据。可以将这些POJO视为DTO的替代方法吗?

评论

但是POJO可以是DTO,DTO可以用POJO来实现。您正在比较苹果和桔子。

为什么好主意会过时?看一下Lisp。除了笑话,我同意欣快感:我通常使用POJO实现DTO。我仍然发现DTO非常简单(KISS)和有用的概念。

没有意义,这是一种反模式,请参阅:数据传输对象是一种耻辱

#1 楼

DTO是一种模式,它独立于实现(POJO / POCO)。 DTO说,由于对任何远程接口的每次调用都是昂贵的,因此对每个调用的响应应带来尽可能多的数据。因此,如果需要多个请求来携带特定任务的数据,则可以将要携带的数据合并到DTO中,以便只有一个请求可以携带所有必需的数据。企业应用程序体系结构模式目录有更多详细信息。

DTO是一个基本概念,不会过时。

评论


您可能会发现它们的名称不同,因为这些天所有人似乎都在重新发明轮子

– Linkerro
2012年10月26日上午10:25

就像“值对象”。

–theD
2012年10月26日10:53

@linkerro:正确:我认为很多人应该花更多的时间来阅读已经发明的东西,而不是自己重新发明。重新发明的东西永远不会那么成熟。

–乔治
2012年11月1日于10:36

@Giorgio那里还有很多开发人员,他们的想法本来就不可能实现。我希望更多的开发人员对他们阅读的每个想法提出质疑。

–埃里克·雷彭(Erik Reppen)
2013年6月4日22:41

#2 楼

DTO作为一个概念(目的是收集要由服务器返回给客户端的数据的对象)当然并不会过时。

有点过时的概念是DTO完全不包含逻辑,仅用于传输数据,并在传输到客户端之前从域对象“映射”,并映射到视图模型在将它们传递到显示层之前。在简单的应用程序中,通常可以将域对象直接用作DTO,并直接传递给显示层,因此只有一个统一的数据模型。对于更复杂的应用程序,您不想将整个域模型公开给客户端,因此从域模型到DTO的映射是必需的。拥有一个单独的视图模型来复制来自DTO的数据几乎是没有道理的。因为它们的域和视图模型不是POJOS,而是直接绑定到框架。

最值得注意的是,在EJB 3标准之前的J2EE中的Entity Bean不是POJO,而是由应用服务器构造的代理对象-根本不可能将它们发送给客户端,因此您有了没有选择拥有单独的DTO层-这是强制性的。

评论


当UI开发人员被迫担任更加通用的角色时,我肯定在我们的代码库中发现了Mapper.Map现象。为什么DTO不能自己映射?

–埃里克·雷彭(Erik Reppen)
2013年6月4日22:39

@ErikReppen的主要好处是将您的域模型与DTO分离。如果您的DTO自己映射,则需要引用您的域模型。

–亚历山大·德克(Alexander Derck)
19年1月3日在22:20

DTO在API中非常有用。如果您只是将内部模型退还给客户,则他们可能会拥有您的所有信息(例如,用户的地址,电子邮件,政府标识符,电话号码等)。使用DTO,您可以映射他们需要的信息以及仅该信息。另外,如果稍后将这些属性之一添加到共享域/ DTO,则默认情况下会将其发送到客户端。您必须添加代码以使该字段不被返回,这(从安全角度而言)比不意外返回一个字段要差。

–ps2goat
19年12月31日在19:30

#3 楼

尽管DTO并不是一种过时的模式,但是它经常被不必要地应用,这可能会使它显得过时。 Java Enterprise社区中的DTO模式是DTO。
DTO被明确定义为分发问题的解决方案。 DTO
是一个粗粒度的数据容器,可以有效地在进程(层)之间传输数据。 〜Adam Bien


来自Martin Fowler:


DTO被称为数据传输对象,因为它们的全部目的是
将数据移入昂贵的远程呼叫。它们是实现
粗粒度接口的一部分,远程接口需要该粗粒度接口才能实现性能。不仅您不需要在本地环境中使用它们,而且它们实际上是有害的,这不仅是因为粗粒度API更难以使用
,还因为您必须完成所有移动数据的工作
从您的域或数据源层到DTO。 〜Martin
Fowler


这里是Java EE特定的示例,该示例常见但错误地使用了DTO模式。如果您不熟悉Java EE,则只需要了解MVC模式:“ JSF ManagedBean”是View使用的类,而“ JPA Entity”是MVC模式中的模型。

例如,假设您有一个JSF ManagedBean。一个常见的问题是,bean是应该直接持有对JPA实体的引用,还是应该维护对某些中间对象的引用,该对象随后将转换为Entity。我听说过这个称为DTO的中间对象,但是如果您的ManagedBeans和Entities在同一个JVM中运行,那么使用DTO模式几乎没有好处。

此外,请考虑Bean验证批注(同样,如果您不熟悉Java EE,请知道Bean验证是用于验证数据的API)。您的JPA实体可能带有@NotNull和@Size验证。如果您使用的是DTO,则需要在DTO中重复这些验证,以便使用远程接口的客户端无需发送消息即可发现其基本验证失败。想象一下在DTO和实体之间复制Bean验证批注的所有额外工作,但是如果您的视图和实体在同一JVM中运行,则无需进行这项额外工作:只需使用实体。

IAmTheDude的企业应用程序体系结构模式目录链接提供了DTO的简要说明,下面是我发现有启发性的更多参考文献: br />如何在JSF + Spring + Hibernate中使用DTO
数据传输对象的优缺点
Martin Fowler对DTO的描述
Martin Fowler解释了DTO的问题-显然,最早在2004年被滥用


评论


有一句话:“ ...,但是,如果您的ManagedBeans和Entities在同一JVM中运行,那么使用DTO模式几乎没有好处”。公司中有许多中型应用程序愚蠢地实施了DTO模式,却没有任何好处。它只是添加了一个无用的“复制层”。创建这些系统的人没有意识到Java EE 5+实体管理器在事务结束时将实体分离并使其成为实际的DTO。因此,对于单JVM Web应用程序,这种模式已经过时了。似乎是J2EE后端开发人员的遗物...

–卡乌
17/12/21在15:09



但是什么是“ JSF ManagedBean”和“ JPA实体”?如果它们没有过时,那么您应该能够使用与框架和语言无关的术语来解释它们。

–U阿瓦洛斯
18年3月12日在4:10

#4 楼

绝对不!最近,我吸取了关于更好地使用DTO而不是使用您的业务对象(可能绑定到您的ORM映射器)的经验教训。因为在一些好的模式书中已经提到它们,所以才使用它们。
我想到的一个典型示例是,当您向第三方公开某种界面时。在这种情况下,您希望保持交换的对象相当稳定,通常可以使用DTO很好地实现。

评论


您可以在对象A中创建方法toJson()并将空值设置为您不想公开的字段,而不是将数据从对象A复制到对象B。如果对于不同的字段有多个端点,则可以使用toJsonXXX(),其中XXX是用例

– Xoke
20 Mar 4 '20 at 18:18



#5 楼

我发现DTO尤其有用的一个地方是包含API响应的逻辑。使用这种模式,可以以可测试的方式轻松管理从对象到各种格式的不同类型的响应。在我目前的角色下使用此模式,我们能够开始测试API的响应格式,这很有价值,因为我们的堆栈在各种客户端(http / mobile)上变得越来越同构。绝对不会过时。

#6 楼

DTO确实非常强大。
一种用途是从多个要传输的对象组成数据。
第二种用途是将数据对象的详细信息隐藏在应用程序的其余部分之外,这可以使您拥有更改数据对象。例如,如果您使用的是mysql数据库,那么您将其更改为mongodb,则数据对象可能会因此而更改。为了避免在应用程序的其余部分中发生更改,您可以使用DTO,然后只需使用依赖项注入来更改映射器即可避免此类更改。