Using ModelMapper to Clone Entities in Spring Boot: A Practical Guide

Viplove Mittal
3 min readJul 17, 2024

In the world of Spring Boot applications, we often find ourselves needing to map data between different object structures. Whether it’s for DTOs, entity transformations, or data migration, it is crucial to have a reliable and efficient way to perform these mappings. This is where ModelMapper comes into play, offering a powerful solution for object-to-object mapping.

This article’ll explore how to use ModelMapper to clone entities in a Spring Boot application, focusing on a practical example involving a user management system.

Setting Up ModelMapper in Your Spring Boot Project

First, let’s add the ModelMapper dependency to our `pom.xml`:

<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.1</version>
</dependency>

Next, we’ll create a configuration class to set up ModelMapper as a bean:

import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ModelMapperConfig {

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

Our Example: User and UserDTO

Let’s consider a scenario where we have a User entity and a UserDTO (Data Transfer Object) that we want to map between. Here are our classes:

@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
private String password;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Address> addresses;
// getters and setters
}

public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String street;
private String city;
private String country;
// getters and setters
}

public class UserDTO {
private Long id;
private String username;
private String email;
private List<AddressDTO> addresses;
// getters and setters
}

public class AddressDTO {
private String street;
private String city;
private String country;
// getters and setters
}

Implementing the Mapping

Now, let’s create a service to handle the mapping between User and UserDTO:

import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;

@Service
public class UserMappingService {

private final ModelMapper modelMapper;

public UserMappingService(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
configureModelMapper();
}

private void configureModelMapper() {
modelMapper.createTypeMap(User.class, UserDTO.class)
.addMappings(mapper -> mapper.skip(UserDTO::setPassword));
}

public UserDTO convertToDTO(User user) {
return modelMapper.map(user, UserDTO.class);
}

public User convertToEntity(UserDTO userDTO) {
return modelMapper.map(userDTO, User.class);
}
}

In this service:

  1. We inject the ModelMapper bean.
  2. We configure the mapper to skip the password field when mapping from User to UserDTO for security reasons.
  3. We provide methods to convert between User and UserDTO in both directions.

Using the Mapping Service

Now that we have our mapping service set up, we can use it in our controllers or other services:

@RestController
@RequestMapping("/api/users")
public class UserController {

private final UserService userService;
private final UserMappingService userMappingService;

public UserController(UserService userService, UserMappingService userMappingService) {
this.userService = userService;
this.userMappingService = userMappingService;
}

@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
User user = userService.getUserById(id);
UserDTO userDTO = userMappingService.convertToDTO(user);
return ResponseEntity.ok(userDTO);
}

@PostMapping
public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {
User user = userMappingService.convertToEntity(userDTO);
User savedUser = userService.saveUser(user);
UserDTO savedUserDTO = userMappingService.convertToDTO(savedUser);
return ResponseEntity.created(URI.create("/api/users/" + savedUser.getId())).body(savedUserDTO);
}
}

Benefits of Using ModelMapper

  1. Simplicity: ModelMapper reduces the amount of boilerplate code needed for object mapping.
  2. Flexibility: It allows for easy customization of mapping behavior.
  3. Performance: ModelMapper is designed to be fast and efficient.
  4. Maintainability: Centralized mapping logic makes it easier to maintain and update as your data models evolve.

Conclusion

ModelMapper provides a powerful and flexible way to handle entity cloning and DTO conversions in Spring Boot applications. By abstracting away the complexities of object mapping, it allows developers to focus on business logic rather than tedious data transformation code.

Remember to always consider the specific needs of your application when implementing mapping solutions. While ModelMapper is a great tool, it’s important to understand its capabilities and limitations to use it effectively in your projects.

Happy coding!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response