Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Explicit Map with Java 8 and ModelMapper?

I learn how to use ModelMapper by official documentation http://modelmapper.org/getting-started/

There is code sample for explicit mapping using java 8

modelMapper.addMappings(mapper -> {
  mapper.map(src -> src.getBillingAddress().getStreet(),
      Destination::setBillingStreet);
  mapper.map(src -> src.getBillingAddress().getCity(),
      Destination::setBillingCity);
});

How to use this code correctly? When I type this code snippet in IDE, IDE show me message cannot resolve method map

enter image description here

like image 630
hudrogen Avatar asked Feb 27 '18 08:02

hudrogen


People also ask

What is ModelMapper map?

ModelMapper uses conventions to determine how properties and values are mapped to each other. Users can create custom conventions, or use one of the supplied conventions.

How does ModelMapper work in Java?

ModelMapper consists of two separate processes: the matching process, where a source and destination type's properties are matched to each other, and the mapping process where matched property values are converted from a source to destination object. A further description of these processes follows.

How do I customize ModelMapper?

You can do this: ModelMapper mm = new ModelMapper(); DogData dd = new DogData(); dd. setName("fido"); dd. setMass(70); DogInfo di = mm.


2 Answers

They missed a step in this example, the addMappings method they use is the addMappings from TypeMap, not from ModelMapper. You need to define a TypeMap for your 2 objects. This way:

// Create your mapper
ModelMapper modelMapper = new ModelMapper();

// Create a TypeMap for your mapping
TypeMap<Order, OrderDTO> typeMap = 
    modelMapper.createTypeMap(Order.class, OrderDTO.class);

// Define the mappings on the type map
typeMap.addMappings(mapper -> {
    mapper.map(src -> src.getBillingAddress().getStreet(), 
                      OrderDTO::setBillingStreet);
    mapper.map(src -> src.getBillingAddress().getCity(), 
                      OrderDTO::setBillingCity);
});

An other way would be to use the addMappings method from ModelMapper. It does not use lambdas and takes a PropertyMap. It is short enough too:

ModelMapper modelMapper = new ModelMapper();
modelMapper.addMappings(new PropertyMap<Order, OrderDTO>() {
  @Override
  protected void configure() {
    map().setBillingStreet(source.getBillingAddress().getStreet());
    map().setBillingCity(source.getBillingAddress().getCity());
  }
});
like image 162
Bentaye Avatar answered Sep 23 '22 06:09

Bentaye


if the source and destination type are different. For example,

@Entity
class Student {
    private Long id;
    
    @OneToOne
    @JoinColumn(name = "laptop_id")
    private Laptop laptop;
}

And Dto ->

class StudentDto {
    private Long id;
    private LaptopDto laptopDto;
}

Here, the source and destination types are different. So, if your MatchingStrategies are STRICT, you won't able to map between these two different types. Now to solve this, Just simply put this below code in the constructor of your controller class or any class where you want to use ModelMapper->

private ModelMapper modelMapper;

public StudentController(ModelMapper modelMapper) {
    this.modelMapper = modelMapper;
    this.modelMapper.typeMap(Student.class, StudentDto.class).addMapping(Student::getLaptop, StudentDto::setLaptopDto);
}
        

That's it. Now you can use ModelMapper.map(source, destination) easily. It will map automatically

modelMapper.map(student, studentDto);
like image 22
Muhammad Saimon Avatar answered Sep 25 '22 06:09

Muhammad Saimon