此答案是stack exchange 上的内容的复制品。恕我直言,应该关闭 OP 以在错误的论坛上发布。它目前也吸引了固执己见的答案,尽管不一定如此,并且与 Java 没有任何特定的联系。
DTO 是一种模式,它独立于实现 (POJO/POCO)。 DTO 说,由于对任何远程接口的每次调用都很昂贵,因此对每次调用的响应都应该带来尽可能多的数据。因此,如果需要多个请求为特定任务带来数据,则可以将要带来的数据组合在一个 DTO 中,以便只有一个请求可以带来所有需要的数据。 Patterns of Enterprise Application Architecture的目录有更多细节。
DTO 是一个基本概念,并不过时。
有点过时的是让 DTO 完全不包含任何逻辑的概念,仅用于传输数据并在传输到客户端之前从域对象“映射”,并在将它们传递给视图模型之前映射到视图模型显示层。在简单的应用中,领域对象往往可以直接作为DTO复用,直接传递到展示层,这样就只有一个统一的数据模型。对于更复杂的应用程序,您不想将整个域模型公开给客户端,因此需要从域模型到 DTO 的映射。拥有一个从 DTO 复制数据的单独视图模型几乎没有任何意义。
然而,这个概念已经过时而不是完全错误的原因是一些(主要是较旧的)框架/技术需要它,因为它们的域和视图模型不是 POJOS,而是直接与框架相关联。
最值得注意的是,在 EJB 3 标准之前的 J2EE 中的实体 Bean 不是 POJO,而是由应用服务器构造的代理对象 - 根本不可能将它们发送到客户端,因此您别无选择单独的 DTO 层 - 这是强制性的。
虽然 DTO 不是一个过时的模式,但它经常被不必要地应用,这可能使它显得过时。
来自 Java 大师 Adam Bien:
Java Enterprise 社区中被滥用最多的模式是 DTO。 DTO 被明确定义为分配问题的解决方案。 DTO 原本是一个粗粒度的数据容器,可以在进程(层)之间有效地传输数据。 ~ 亚当·比恩
来自马丁·福勒:
DTO 被称为数据传输对象,因为它们的全部目的是在昂贵的远程调用中传输数据。它们是实现远程接口性能所需的粗粒度接口的一部分。您不仅在本地环境中不需要它们,而且它们实际上是有害的,因为粗粒度 API 更难使用,而且您必须完成将数据从域或数据源层移动到 DTO 的所有工作。 ~ 马丁·福勒
这是一个 Java EE 特定示例,说明了 DTO 模式的常见但不正确使用。如果您对 Java EE 不熟悉,只需了解 MVC 模式即可:“JSF ManagedBean”是 View 使用的类,“JPA Entity”是 MVC 模式中的 Model。
例如,假设您有一个 JSF ManagedBean。一个常见的问题是 bean 是应该直接持有对 JPA 实体的引用,还是应该维护对稍后转换为实体的中间对象的引用。我听说这个中间对象被称为 DTO,但是如果您的 ManagedBeans 和实体在同一个 JVM 中运行,那么使用 DTO 模式几乎没有什么好处。
此外,请考虑 Bean Validation 注解(同样,如果您不熟悉 Java EE,请知道 Bean Validation 是一种用于验证数据的 API)。您的 JPA 实体可能使用 @NotNull 和 @Size 验证进行注释。如果您使用的是 DTO,您需要在 DTO 中重复这些验证,以便使用您的远程接口的客户端不需要发送消息来发现他们未通过基本验证。想象一下在 DTO 和实体之间复制 Bean Validation 注释的所有额外工作,但是如果您的视图和实体在同一个 JVM 中运行,则无需承担这些额外工作:只需使用实体即可。
Catalog of Patterns of Enterprise Application Architecture 提供了 DTO 的简明解释,以下是我发现的更多参考资料: