Issue
There is the Customer entity which has a one to many relationship to entity Address,so there is a List<Address> addresses=new ArrayList<>
in Customer.Entity Address has an Email field.
For instance,Customer holds an Address ArrayList with two elements.To get an email from the first customer you do customer.getAddresses.get(0).getEmail
So for Customer ID =6 there can be 2 Addresses with one email per Address. When building the DTO I just need the Customer Id and the Email.
So in that case I would like two rows in the DTO 6 [email protected] 6 [email protected]
Like doing an SQL query and getting two rows back for the same id.
Is there a way to do that with Mapstruct without doing any sql? Like iterating over a collection?
Solution
I am not sure that i understand what you want. Mapstruct is used for mapping and not applying logic. The case that you describe is something that i would solve eiter with SQL or with onboard java utilities.
My approach looks like this
package mapping;
import lombok.Builder;
import lombok.Data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MappingMain {
public static void main(String[] args) {
Customer customer = Customer.
builder()
.id(1)
.name("John")
.adresses(Arrays.asList(
Address.builder().email("[email protected]").street("exampleStreet1").build(),
Address.builder().email("[email protected]").street("exampleStreet2").build()))
.build();
//single customer
List<ResultingDTO> resultingDTOS =
customer.getAdresses()
.stream()
.map(Address::getEmail)
.map(email ->
ResultingDTO.builder().email(email).id(customer.getId()).build()
)
.collect(Collectors.toList());
System.out.println(resultingDTOS);
//multiple customer "select" by id
List<Customer> listOfCustomers = Arrays.asList(customer, Customer.builder().id(33).build());
List<ResultingDTO> resultList = new ArrayList<>();
listOfCustomers
.stream()
.filter(singleCustomer -> singleCustomer.getId() == 1)
.forEach(customerWithId_1 -> {
resultList.addAll(customerWithId_1.getAdresses()
.stream()
.map(Address::getEmail)
.map(email ->
ResultingDTO.builder().email(email).id(customer.getId()).build()
)
.collect(Collectors.toList()));
});
System.out.println(resultList);
}
@Data
@Builder
public static class Customer {
private int id;
private String name;
private List<Address> adresses;
}
@Data
@Builder
public static class Address {
private String street;
private String email;
}
@Data
@Builder
public static class ResultingDTO {
private int id;
private String email;
}
}
Answered By - GJohannes
Answer Checked By - Mary Flores (JavaFixing Volunteer)