Mapping from multiple objects to one destination object

In this post under MapStruct, I will explain with example how to map attributes from multiple objects to attributes of one single destination object.

For our example I will two source class as shown below

Person

package package4;

public class Person {
    private int id;
    private String name;
    private int age;
    private char sex;

    //Removed the getter and setter for brevity
}

Address

package package4;

public class Address {
    private int id;
    private String address;
    private String city;
    private String state;
    private String country;

    //Removed the getter and setter for brevity
}

The destination class will be as shown below

package package4;

import java.util.Objects;

public class PersonAddressDTO {
    private int personId;
    private int addressId;
    private String name;
    private int age;
    private char sex;
    private String address;
    private String city;
    private String state;
    private String country;

    //Removed getter and setter for brevity

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(this.personId).append(",");
        stringBuilder.append(this.name).append(",");
        stringBuilder.append(this.age).append(",");
        stringBuilder.append(this.sex).append(",");
        stringBuilder.append(this.addressId).append(",");
        stringBuilder.append(this.address).append(",");
        stringBuilder.append(this.city).append(",");
        stringBuilder.append(this.state).append(",");
        stringBuilder.append(this.country).append(",");
        return stringBuilder.toString();
    }
}

As you can see, the destination class has attributes which are combination of attributes from source class “Person” and “Address”.

Now to map attributes from the source objects (i.e., “Person” and “Address”) to attributes of “PersonAddressDTO” object. We will write a Mapper interface.

Please note “Person” class and “Address” class both has “id” attribute (i.e., attribute with same name).

We have to map the “id” attribute from “Person” class to “personId” and “id” attribute from “Address” class to “addressId” in the destination class “PersonAddressDTO”.

The Mapper interface will be as shown below

PersonAddressMapper

1  package package4;
2  
3  import org.mapstruct.Mapper;
4  import org.mapstruct.Mapping;
5  
6  @Mapper
7  public interface PersonAddressMapper {
8      @Mapping(target = "personId", source="person.id")
9      @Mapping(target = "addressId", source="address.id")
10     PersonAddressDTO getDTOFromModel(Person person, Address address);
11 }

The method that will do the mapping is “getDTOFromModel”. This method takes two objects one of “Person” class and another of “Address” class and return an object of “PersonAddressDTO” class.

Based on the method signature, the “MapStruct” framework will deduce that it has to map attributes from both “Person” and “Address” objects to attributes in “PersonAddressDTO” object.

MapStruct assumes that attribute names are same in both source and destination objects. It uses the attribute names to decide which attribute value from source object has to go to which attribute in destination object.

In our case attribute from source and destination class match, except “id” attribute in both “Person” and “Address” class and “personId” and “addressId” from “PersonAddressDTO” class. They differ.

To map the “id” attribute value from “Person” class to “personId” attribute in “PersonAddressDTO” and to map “id” attribute value from “Address” class to “addressId” attribute in “PersonAddressDTO” class. I will take help of “@Mapping” annotation as shown at line 8 and 9.

Just mentioning “id” attribute as shown below won’t work

    @Mapping(target = "personId", source="id")
    @Mapping(target = "addressId", source="id")

MapStruct will get confuse, it will not be able to decide whether to take the “id” attribute from “Person” or “Address” class and map to which attribute (i.e., “personId” or “addressId”) in destination class. So we have to mention the source object names in the annotation also.

In this way we can map attributes from multiple objects to attributes of single object.

Leave a comment