Hi all in this blog we ‘ll learn about MapStruct in spring boot. We ‘ll see what is MapStruct and what issue it resolve for spring boot applications. So Let’s start and explore mapstruct.
What is MapStruct
MapStruct is a java library that helps us to automatically convert one object into another object at compile time. So as a spring boot developer we know about DTO (Data Transfer Object) and Entity. We use these two frequently in our application. And we are pretty sure that you also face the issue while converting DTO to Entity for saving object into the database. Mostly we use MapStruct for this (DTO to Entity and Entity to DTO) object conversion in spring boot.
For example you have a user entity that contains many field, lets say your entity class has around more then 20 fields. Some of them we set as per business logic but some of them we need from user. So we expect them in the payload in our endpoint in DTO’s. And if are using ORM like JPA then we can save only entity not these DTO’s. So we have to manually update these entity fields from DTO’s. We need to create object of Entity and then we set the value using setter method.
User user = new User();
user.setName(dto.getName);
...
// Need to set one by oneCode language: JavaScript (javascript)
It’s painful right setting these values one by one. It’s ok if entity is small but what if entity grow and have more then 50 fields. It ‘ll hard to set all values one by one using setter method and code ‘ll also look ugly.
In short MapStruct helps to convert DTO’s to Entity and Entity to DTO’s at compile time. It reduce the effort to write boilerplate code and do that stuff for us automatically at compile time.
So to resolve this issue MapStruct comes into the picture.
How to use MapStruct in Spring boot
It’s very easy to use MapStruct in spring boot. Let’s first understand what we are going to do in this example. We create a Spring boot project with PostgreSQL and JPA. Then we create a entity class and a dto and see how this conversion happens at compile time. We are using java 21 version for this example. So let’s start now.
To use MapStruct in spring boot we have to follow below steps.
1- Add the MapStruct dependency in pom.xml file
2- Create a Entity and DTO class.
3- Create MapStruct Mapper interface and decleare the method to convert DTO to Entity and Entity to DTO.
1- First add the Below dependency in your pom.xml file.
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
<scope>provided</scope>
</dependency>Code language: HTML, XML (xml)
mapstruct dependency helps to provide mapstruct annotations like @Mapper, @Mapping, @Mappings. And mapstruct-processor dependency reads the @Mapper interface and generates the implementation class for this mapper which contains the logic of object to object mapping.
2- Create a entity and dto class.
User.java
package com.example.mapstruct.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "users")
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String email;
private double salary;
private String mobileNumber;
}Code language: CSS (css)
As we are using java 21 so we ‘ll create a Record for dto. It’s upto you if you want to create a pojo class with getter-setter or you can use the same record as our.
UserDTO.java
package com.example.mapstruct.DTO;
public record UserDTO(String name, String email) {
}Code language: CSS (css)
Now it’s time to see the magic. Think for a moment if we use the same way that we use to do to update entity object from dto. We first create the entity class object then set the entity fields with dto fields value. It’s easy if we have small number of fields in entity but it can become nightmare if we have a huge entity.
Let’s see the mapstruct magic now. Just create a simple interface.
MapStruct Flow
UserMapper.java
package com.example.mapstruct.mapper;
import com.example.mapstruct.DTO.UserDTO;
import com.example.mapstruct.entity.User;
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface UserMapper {
UserDTO toDto(User user);
User toEntity(UserDTO dto);
}Code language: CSS (css)
You can see we create a interface and two methods toDto and toEntity. These method is use to do the object mapping. You can see we are accepting one type of object and returning the other type of object. In this example in toDto method we are accepting User entity object and returning userDTO and other method do the reverse of it.
@Mapper is the mapstuct annotation that helps us to generate the implementation of this interface at runtime.
componentModel = “spring” defines that this implementation class is of type component and later we ‘ll use it as dependency in the service classes. “spring” value is fix for spring boot application you can not change it. Other value that componentModel supports are given below:
- default
- spring
- cdi
- spring
- jsr330
We can not write any custom value in componentModel . for “spring” means @Component in mapstruct.
Now compile your project. As we are using the maven so we just run the below command.
mvn clean install -DskipTests
Once project build completed see the target folder. Inside that open generated-sources, If everything goes good you ‘ll see the implementation of the UserMapper that we created. It is generated by the mapstruct for us. You can go and check this code it’s the same boilerplate code that we use to write.

Now test if it’s working or not. What you can do create a service class and inject the UserMapper interface dependency in service class. And using this method you can play with change dto to entity or vice versa and save entity into the DB.
Let’s create a controller class and a repository that use JPARepository. And create a service class where we convert dto to entity and save into DB.
UserController.java
package com.example.mapstruct.controller;
import com.example.mapstruct.DTO.UserDTO;
import com.example.mapstruct.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping("/user")
public ResponseEntity<?> createUser(@RequestBody UserDTO userDTO){
return userService.createUser(userDTO);
}
}Code language: CSS (css)
UserRepository .java
package com.example.mapstruct.repository;
import com.example.mapstruct.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}Code language: CSS (css)
UserService .java
package com.example.mapstruct.service;
import com.example.mapstruct.DTO.UserDTO;
import com.example.mapstruct.entity.User;
import com.example.mapstruct.mapper.UserMapper;
import com.example.mapstruct.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
private final UserRepository userRepository;
public ResponseEntity<?> createUser(UserDTO userDTO) {
User entity = userMapper.toEntity(userDTO);
entity.setMobileNumber("8077777777");
User saveUser = userRepository.save(entity);
return ResponseEntity.ok(saveUser);
}
}Code language: JavaScript (javascript)
Now run your project and call the rest endpoint with some data. You ‘ll see whatever data we are sending in dto automatically map to entity. And same you can see in the database table also.

Verify record in database.

@Mapping annotation of MapStruct
This mapper works only when DTO and entity field name is same. But it ‘ll not be the case always right. So if we have different field name in dto and entity then we need to use @Mapping annotation.
Say our Entity class has field userEmail and dto has email. Now if you try it ‘ll not work and in your DB email field show blank. So to do the mapping we need to use @Mapping annotation.





Note:
If you have configured the <annotationProcessorPaths> in your maven plugin to restrict the annotationProcessor. You have to explicitly add below in your annotationProcessorPaths otherwise your mapstruct ‘ll not work. If you want to restrict annotationProcessor then mapstruct must be added here else remove this <annotationProcessorPaths>from your pom file then existing setup ‘ll work.
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
<!-- Lombok + MapStruct bridge (VERY IMPORTANT) -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>Code language: HTML, XML (xml)

You can checkout complete code from Github using below URL.
Hope you like the blog. If you like it please share with other and helps us to grow. Please share your feedback in our comment section.
If you need blog on any specific topic please mention in our comment section we ‘ll try to cover that in our upcoming blogs.
Other blogs you may like.
Distributed Logging in spring boot microservices
GoDaddy Domain name mapping of spring boot EC2 instance on AWS