Using ModelMapper in Spring Boot — article by Ayesh Niroshan, Software Engineer at ArkStatic

Using ModelMapper in Spring Boot for Clean and Simple Object Mapping

When building a Spring Boot application, you often need to convert between DTOs (Data Transfer

Objects) and Entities. Doing this manually can make your code long, repetitive, and hard to maintain.

That’s where ModelMapper becomes incredibly useful.

ModelMapper automatically maps one object to another when the field names and types match, and it

also allows custom configurations when they don’t.

In this article, we’ll explore:

  • Why do we use ModelMapper?
  • How to add it to a Spring Boot project.
  • Real-world use case.
  • Example entity, DTO, and mapping logic.
  • Advanced custom mappings.
Why Use ModelMapper?
  • Reduces repetitive setter/getter conversions.
  • Handles nested structures.
  • Easy to customize.
  • Reduces boilerplate in controllers and services.
  • Makes code cleaner and more maintainable.
Add ModelMapper to Your Spring Boot Project
  • Add the dependency in your pom.xml:
				
					<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>3.2.0</version>
</dependency>

				
			
  • If using gradle, in build.gradle file:
				
					implementation 'org.modelmapper:modelmapper:3.2.4'
				
			

Then register it as a Spring Bean:

				
					@Configuration
public class AppConfig {

    @Bean
    public ModelMapper modelMapper() {
        return new ModelMapper();
    }
}

				
			

Real World Example: Customer Management

Customer Entity:

				
					@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String fullName;
    private String email;
    private String phone;
    private String city;
    private LocalDate registeredDate;
}

				
			

Notice the DTO does not contain registeredDate.

This is common because DTOs send only what the client needs.

				
					public class CustomerDTO {

    private Long id;
    private String fullName;
    private String email;
    private String phone;
    private String city;
}

				
			
Mapping Entity DTO Using ModelMapper

Convert Entity to DTO

				
					public CustomerDTO convertToDto(Customer customer) {
    return modelMapper.map(customer, CustomerDTO.class);
}
				
			

Convert DTO to Entity

				
					public Customer convertToEntity(CustomerDTO dto) {
    return modelMapper.map(dto, Customer.class);
}
				
			

That’s all ModelMapper needs when field names match.

Service Layer Example (Real API Use Case)
				
					import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import java.time.LocalDate;

@Service
public class CustomerService {

    private final CustomerRepository customerRepository;
    private final ModelMapper modelMapper;

    // Constructor Injection
    public CustomerService(CustomerRepository customerRepository, ModelMapper modelMapper) {
        this.customerRepository = customerRepository;
        this.modelMapper = modelMapper;
    }

    public CustomerDTO createCustomer(CustomerDTO dto) {
        Customer customer = modelMapper.map(dto, Customer.class);
        customer.setRegisteredDate(LocalDate.now());
        customer = customerRepository.save(customer);
        return modelMapper.map(customer, CustomerDTO.class);
    }

    public CustomerDTO getCustomer(Long id) {
        Customer customer = customerRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Customer not found"));
        return modelMapper.map(customer, CustomerDTO.class);
    }
}

				
			
Advanced Case: When Field Names Do NOT Match

Let’s say your DTO contains fields that are different from the Entity.

DTO Example

				
					public class CustomerDTO {
        private String name;
        private String email;
    }
				
			

Entity Example

				
					public class Customer {
    private String fullName;
}
				
			

Field name mismatch: name fullName.

Custom Mapping

				
					ModelMapper mapper = new ModelMapper();

mapper.typeMap(CustomerDTO.class, Customer.class).addMappings(m -> {
          m.map(CustomerDTO::getName, Customer::setFullName);
});

				
			

Now, mapping will still work properly.

Mapping Nested Objects

Imagine:

Customer Entity Contains Address Entity

				
					public class Address {
    private String street;
    private String city;
    private String zip;
}
				
			
				
					@Entity
public class Customer {
    ...
    @OneToOne
    private Address address;
}

				
			

CustomerDTO Flattens the fields

				
					public class CustomerDTO {
    private String fullName;
    private String city;
    private String street;
}
				
			

Custom Mapping

				
					modelMapper.createTypeMap(Customer.class, CustomerDTO.class).addMappings(mapper -> {
        mapper.map(src -> src.getAddress().getStreet(), CustomerDTO::setStreet);
        mapper.map(src -> src.getAddress().getCity(), CustomerDTO::setCity);
    });

				
			

ModelMapper handles nested object transformations smoothly.

Conclusion

ModelMapper is a powerful and simple tool that:

  • Removes repetitive mapping code
  • Makes controllers and services cleaner
  • Handles advanced/custom mappings
  • Works perfectly with REST APIs and DTO patterns

If you’re building a Spring Boot project with entities + DTOs (which almost every real-world app does),

ModelMapper can save you tons of time and reduce errors.

Author:

Ayesh Niroshan, Software Engineer at ArkStatic

Ayesh Niroshan

Share Now:

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments