【问题标题】:How to map a DTO to multiple entities?如何将 DTO 映射到多个实体?
【发布时间】:2019-02-01 17:03:32
【问题描述】:

我正在编写一个 Spring 应用程序,它有两个通过一对多关系关联的实体,我们称它们为母亲和孩子。

当我通过 POST 请求创建一个母实体时,我希望自动创建一个子实体。使用 @OneToMany 和 @ManyToOne 注释,效果很好。至少,只要我在 MotherService 中提供孩子信息。

这是我的代码

Mother.java

@Entity
@Table(name="mother")
public class Mother{
   @Id
   @Column(name="id", updatable = false, nullable = false)
   private Long id;

   @Column(name="name")
   private String name;

   @OneToMany(mappedBy = "mother", cascade = CascadeType.ALL, orphanRemoval = true)
   private List<Kid> kidList = new ArrayList<>();

   //constructor, getter, setter

   private void addKid(Kid kid) {
      this.kidList.add(kid);
      kid.setMother(this);
   }
}

Kid.java

@Entity
@Table(name="kid")
public class Kid{
   @Id
   @Column(name="id", updatable = false, nullable = false)
   private Long id;

   @Column(name="name")
   private String name;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "mother_id", nullable=false)
   private Mother mother;

   //constructor, getter, setter
}

MotherController.java

@RestController
@RequestMapping("mothers")
public class MotherController {

   @Autowired
   private MotherService motherService;

   MotherController(MotherService motherService) {
       this.motherService = motherService;
   } 

   @PostMapping
   Mother createMother(@RequestBody Mother mother)  {
       return this.motherService.createMother(mother);
   }
}

MotherService.java

@Service
public class MotherService {

   private MotherRepository motherRepository;

   @Autowired
   public MotherService (MotherRepository motherRepository) {
       super();
       this.motherRepository= motherRepository;
   }

   public Mother createMother(Mother mother)  {

       Kid kid = new Kid("Peter");

       mother.addKid(kid);

       return this.motherRepository.save(mother);
   }
}

到目前为止,母亲和孩子的存储库扩展了 JpaRepository,没有任何自定义方法。

我的 POST 请求类似于(使用 Postman)

{
   "name":"motherName"
}

现在创建了一个名为“motherName”的母亲和一个名为“Peter”的孩子。

我的想法:使用 DTO

我现在尝试实现一个 DTO,其中包含母亲姓名和孩子姓名,将 MotherService 中的这些信息映射到实体并通过相应的存储库保存它们,这样我就可以在 POST 请求中定义这两个名称。

motherDto.java

public class mother {
   private String motherName;
   private String kidName;

   //getter, setter

}

所以当我发帖时

{
  "motherName":"Susanne",
  "kidName":"Peter"
}

甚至更好

{
   "mother": {
       "name":"Susanne"
   },
   "kid": {
       "name":"Peter"
   }
}

创造了一个名叫 Susanne 的母亲和一个名叫 Peter 的孩子。

我的问题是

如何将 DTO 映射到两个实体?

或者我做错了什么?有没有更简单的方法来实现我的目标?

【问题讨论】:

  • 你可以让母亲和孩子实现一个接口,然后创建一个构造函数thingDto(Person p),或者只制作2个thingDto(Mother m)和thingDto(Kid k)
  • 在 DTO 课程中,您应该同时拥有母亲和孩子。私人母亲母亲;私人小孩; //getter 和 setter
  • 好的,这个接口或thing2mother 是什么样子的?以及如何调整服务以从motherDto映射母亲/孩子?你有例子或教程吗?您有示例或教程吗?
  • 类似的东西:pastebin.com/K6J7VxX6

标签: java spring spring-mvc spring-data-jpa dto


【解决方案1】:

我知道这是老问题,可能早就解决了,但让我对这个主题提出不同的看法。

另一种选择是设计一个 DTO,仅用于创建您提到的两个实体。您可以将此称为 MotherChildCreationDTO 或类似名称,这样名称就已经传达了它的用途,并且可能会创建一个使用 DTO 的 REST 目标。

非对称 DTO(接收和发送)是一种既定模式,并且 DTO 以任何方式与 REST 控制器紧密耦合。

【讨论】:

  • 谢谢,这正是我最后所做的:)
【解决方案2】:

第一个解决方案:

您不能使用 DTO 并在 Spring MVC 中发送具有与 MotherkidsJackson 相同结构的 JSON 为您正确反序列化它。

{
 id:2,
 name:'sarah'
 kidList:[{id:546,name:'bob'},{id:478,name:'tom'}]
}

第二种解决方案:

如果您想在 JSON 和模型中使用不同的结构,您可以使用 Jackson 注释,如 @JsonProperty@JsonDeserialize。阅读this like了解更多信息。

第三种解决方案:

您可以使用DozzerMapper 在您的DTO 和您的模型之间进行复杂的映射。您定义 XML 文件以将每个模型映射到您的 DTODozzerMapper 将您的 DTO 映射到您的模型。阅读 this link 了解更多信息。

【讨论】:

    【解决方案3】:

    你有两种方法:

    1. 自行将 DTO 映射到实体。在这种情况下,您应该创建自定义映射器并定义 DTO 应如何转换为实体。然后只需注入并在服务中使用您的自定义映射器。
    2. 使用现有映射器库之一。例如,好的候选人是MapStructModelMapper。您可以在相应的入门指南中找到使用示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-13
      • 2021-12-31
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      相关资源
      最近更新 更多