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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将DTO映射到多个实体?相关的知识,希望对你有一定的参考价值。

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

当我通过POST请求创建一个母实体时,我希望自动创建一个kid实体。使用@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
}

mother controller.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);
   }
}

mother service.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请求中定义这两个名称。

mother D to.Java

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

   //getter, setter

}

所以当我发布POST时

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

甚至更好

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

一位名叫苏珊娜的母亲和一个名叫彼得的小孩被创造出来。

我的问题是

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

或者我没有得到正确的答案?有没有更简单的方法来实现我的目标?

答案

第一解决方案

你不能使用DTO并发送你的JSONMotherkidsJackson相同的结构在Spring MVC正确反序列化它。

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

二解决方案:

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

第三种方案:

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

另一答案

你有两种方式:

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

以上是关于如何将DTO映射到多个实体?的主要内容,如果未能解决你的问题,请参考以下文章

如何在避免复杂对象的情况下将 dto 映射到实体

如何将OData查询与DTO映射到另一个实体?

如何使用 AutoMapper 将 json 请求 dto 中的 OData 枚举字符串映射到实体枚举属性

NestJS > TypeORM 将复杂实体映射到复杂 DTO

将 DTO 映射到后端实体

将验证属性从域实体映射到 DTO