MVC 架构 DTO/Model mapping/conversion

MVC architecture DTO/Model mapping/conversion

使用Spring MVC 我们通常会看到Controller、Service 和Repository 层。 Repository 层使用 Entity 模型,它与数据库是一对一的映射。我想到了以下 -

  1. Service层是否应该使用相同的Entity模型?
  2. Service层是否应该使用单独的Domain模型?如果是,那么 to/fro 映射应该在服务层完成吗?
  3. Controller层我们应该使用相同的Domain模型吗?
  4. Controller层是否应该使用单独的DTO模型?如果是,那么 to/fro 映射应该在 Controller 层完成?
  5. 我们有什么简单的方法可以不用写太多冗长的代码来做映射吗?我过去用过几次推土机。

这个问题可能有人问过,但我找不到。所以请原谅我重复的问题。

1) 是的,

2) 没有,

3,4) 使用实体进行输出,但使用 CommandObjects 和 DTO(但不是实体)进行输入。这取决于您的体系结构,但我不希望客户端操纵您实体的每个字段,那么您需要将用于 request-mapping(命令对象)的对象与您的域实体分开。

  1. 是的。
  2. 没有。该服务应在存储库对象返回的实体模型上工作。
  3. 没有。控制器应使用 DTO。 DTO 应包含表单字段和验证注释(如果您使用的是 JSR303)。
  4. 是的。 DTO 在控制器层中使用。 DTO 应该公开一个接受实体模型的构造函数。实体模型到 DTO 的转换是在这个构造函数中完成的。实体模型的情况相同。实体模型还应该公开一个重载的构造函数,它接受 DTO 对象作为参数。 DTO 到实体模型的转换应该在这里发生。
  5. DTO (Entity model as arg) 和 Entity model (DTO as arg) 的重载构造函数很冗长。

整个服务层使用的实体模型应该是一样的。 根据您的架构和应用程序的复杂性,您可能希望在服务和控制器层中使用不同的域模型。 我的建议是:

  • 服务始终在使用数据库检索和存储的实体上工作
  • 服务始终采用 DTO 或简单类型作为参数,return 仅采用 DTO。为什么?因为 DTO 与数据库分离,您既不会 运行 进入 LazyInitializationException 也不必使用 open-session-in-view anti-pattern.
  • 将 DTO 视为服务和控制器之间共享的唯一模型
  • 对于实体和 DTO 对象之间的映射,我建议使用 ModelProjector。它非常简单、精简并留下最小的足迹

ModelProjector 通过匹配 属性 名称简单地将一个模型映射到另一个模型。如果它们不匹配,你可以用注解告诉它。也可以将复杂的实体层次结构映射到 "flattened" 数据结构上,使用非常直接的注解。实体 类 保持不变。