I have that relationships (Spring Boot JPA Implementation):
One Person have multiples Addresses
One Address contains one Country
public class Person {
private Integer id;
private Integer name;
private Integer age;
//relations
}
public class Address {
private Integer id;
private Integer person_id;
private String street;
private String city;
private String country_id;
private Boolean preferred;
//relations
}
public class Country {
private Integer id;
private Integer description;
//relations
and i want return a DTO in that way
public class PersonDto {
private Integer id;
private Integer name;
private Integer age;
private String street;
private String city;
private Integer country //description;
but in fact i want
- only return preferred address of person (only can have one).
- Get only Country description in nested class of Address
It's possible with ModelMapper (AddMapping Strategy)
Thanks,
CodePudding user response:
One of the options is doing it with a Converter.
import org.modelmapper.Converter;
import org.modelmapper.spi.MappingContext;
public class PersonToDtoConverter implements Converter<Person, PersonDto> {
@Override
public PersonDto convert(MappingContext<Person, PersonDto> context) {
Person source = context.getSource();
PersonDto destination = context.getDestination();
if (destination == null) {
destination = new PersonDto();
}
destination.setId(source.getId());
destination.setName(source.getName());
destination.setAge(source.getAge());
Address address = source.getAddresses().stream().filter(Address::getPreferred).findFirst().orElse(null);
if (address != null) {
destination.setStreet(address.getStreet());
destination.setCity(address.getCity());
destination.setCountry(address.getCountry().getDescription());
}
return destination;
}
}
Then you need to register the converter with the ModelMapper instance.
import org.modelmapper.ModelMapper;
import java.util.ArrayList;
import java.util.List;
public class Mappings {
public static void main(String[] args) {
//setup
Country germany = new Country();
germany.setId(1);
germany.setDescription(11);
Address address = new Address();
address.setCountry(germany);
address.setCity("Munich");
address.setId(1);
address.setCountry_id("DE");
address.setStreet("some street");
address.setPreferred(true);
address.setPerson_id(1);
Person person = new Person();
person.setId(1);
person.setAge(29);
person.setName(111);
List<Address> addresses = new ArrayList<>();
addresses.add(address);
person.setAddresses(addresses);
//convert
ModelMapper modelMapper = new ModelMapper();
modelMapper.addConverter(new PersonToDtoConverter());
PersonDto personDto = modelMapper.map(person, PersonDto.class);
System.out.println(personDto);
}
}
CodePudding user response:
You can manually define mappings containing arbitrary logic, e.g.:
ModelMapper mm = new ModelMapper();
mm.typeMap(Person.class, PersonDto.class).addMappings(mapper -> {
mapper.map(
person -> { // the source object
for(Address address : person.getAddresses()){
if(address.isPreferred() && address.getCountry() != null)
return address.getCountry.getDescription();
}
return null; // or default country if no address is preferred / etc...
},
PersonDto::setCountry); // corresponding setter of the DTO
});
var myDto = mm.map(myPerson, PersonDto.class);
