How to map a DTO to multiple entities?

I'm writing a Spring Application, which has two entities that are related by a one to many relationship, lets call them mother and kid.

When I create a mother entity via POST request, I want a kid entity be created automatically. Using the @OneToMany and @ManyToOne annotations, that works fine. At least, as long as I provide the kid information within the MotherService.

Here is my code

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);
   }
}

The repositories for mother and kid extend the JpaRepository without any custom methods so far.

My POST request is something like (using Postman)

{
   "name":"motherName"
}

Now a mother is created with a name "motherName" and a kid with the name of "Peter".

My idea: Using a DTO

I now try to implement a DTO, that contains the mothers name and the kids name, map this information in the MotherService to the entities and save them via the corresponding repository, so I can define both names in the POST request.

motherDto.java

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

   //getter, setter

}

So when I POST

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

or even better

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

a mother with name Susanne and a kid with name Peter are created.

My question is

How do I map a DTO to two entities?

Or do I not get something right? Is there an easier way to achieve my goal?

I know this is old and probably long solved, but let me offer a different take on the subject.

Another option would be to design a DTO solely for the purpose of creating the two entities you mentioned. You could call this MotherChildCreationDTO or something like that so the name already conveys its use and maybe create a REST-target consuming the DTO.

Asymmetric DTOs (receiving and sending) are an established pattern, and the DTOs are closely coupled to the REST controller any way.

If you want to map the same database table to two entities, you should create a simple inheritance hierarchy. The superclass should be abstract and contain all attributes that are shared by both entities. You should map it as a mapped superclass so that it is not an entity itself. 1

First solution:

You can don't use DTO and send your JSON with same structure of Mother and kids and Jackson in Spring MVC deserialize it correctly for you.

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

Second solution:

If you want to different structure in JSON and Models and you can use Jackson annotation like @JsonProperty or @JsonDeserialize. Read this like for more information.

Third solution:

You can use DozzerMapper for complex mapping between your DTO and your Model. you define XML's file for mapping each model to your DTO and DozzerMapper map your DTO to your models.Read this link for more information.

To accomplish this, you can define a data transfer object (DTO). A DTO is an object that defines how the data will be sent over the network. Let's see how that works with the Book entity. In the Models folder, add two DTO classes:

You have 2 ways:

  1. Map DTO to entities by yourself. In this case, you should create custom mapper and define how exactly DTO should be converted to entity. Then just inject and use your custom mapper in service.
  2. Use one of existing mapper libraries. For example, good candidates are MapStruct and ModelMapper. You can find usage examples in corresponding getting started guides.

This hub will allow multiple other projects to query for and receive certain data. Because we want to use Entity Framework for the data-access layer and WCF for the service layer, we figured we could just use the created Entity Framework Code First classes as DataContracts over WCF. Something like this:

To avoid having to write cumbersome/boilerplate code to map DTOs into entities and vice-versa, we are going to use a library called ModelMapper. The goal of ModelMapper is to make object mapping easy by automatically determining how one object model maps to another.

DTO to Entity and Entity to DTO Conversion Almost in every RESTful Web Service application, I have to do the DTO to Entity and then Entity to DTO conversion. DTO stands for Data Transfer Object and is a simple Plain Old Java Object which contains class properties and getters and settings methods for accessing those properties.

Both Entity Framework and AutoMapper have received multiple enhancements since this article was written, making some of the objections to using them together less relevant. To offer an analogy, both hammers and screws are good for building houses, but driving a screw with a hammer is a bad way of using both.

Comments
  • you can either have mother and kid implement an interface and then create a constructor thingDto(Person p) or just make 2 thingDto(Mother m) and thingDto(Kid k)
  • In DTO class you should have both mother and kid. private Mother mother; private Kid kid; //getter and setter
  • Ok and how does this Interface or thing2mother look like? And how do I have to adjust the service to map the mother/kid from the motherDto? Do you have an example or tutorial? Do you have an example or tutorial?
  • Something like that: pastebin.com/K6J7VxX6
  • Thanks, that's exactly what I did in the end :)