In a previous couple of tutorials, we created a Spring boot project, built CRUD Restful web services with DTO, and used the ModelMapper library to convert the JPA entity into DTO and vice versa.
Refer to previous tutorials:
Spring Boot 3 CRUD RESTful WebServices with MySQL Database
Spring Boot DTO Example Tutorial
Spring Boot ModelMapper Example - Map Entity to DTO
In this tutorial, we will learn how to use the MapStruct library to map the JPA entity into DTO and vice versa in the Spring boot application.
MapStruct Library Overview
The MapStruct is an annotation-based code generator/mapper which greatly simplifies the mapping implementations of Java Beans. It follows convention over configuration and uses plain method invocations. MapStruct operations are very fast, type-safe, and easy to understand.Check the official doc to read more about MapStruct at https://mapstruct.org/
Prerequisites
This tutorial is a continuation of below three tutorials so first, create CRUD REST APIs using below tutorials:
Spring Boot 3 CRUD RESTful WebServices with MySQL Database
Spring Boot DTO Example Tutorial
Spring Boot ModelMapper Example - Map Entity to DTO
The complete source code of this tutorial is available on my GitHub repository at Spring Boot CRUD RESTful WebServices
Development Steps
1. Add Maven Dependencies
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
Let’s also add the annotationProcessorPaths section to the configuration part of the maven-compiler-plugin plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
Next, add the version properties to the properties section: <properties>
<java.version>17</java.version>
<org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
<org.projectlombok.version>1.18.20</org.projectlombok.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>
2. User JPA Entity and UserDto
Here is our User JPA entity:package net.javaguides.springboot.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String lastName;
@Column(nullable = false, unique = true)
private String email;
}
package net.javaguides.springboot.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String lastName;
@Column(nullable = false, unique = true)
private String email;
}
package net.javaguides.springboot.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
private Long id;
private String firstName;
private String lastName;
private String email;
}
3. Create UserMapper
package net.javaguides.springboot.mapper;
import net.javaguides.springboot.dto.UserDto;
import net.javaguides.springboot.entity.User;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface AutoUserMapper {
AutoUserMapper MAPPER = Mappers.getMapper(AutoUserMapper.class);
UserDto mapToUserDto(User user);
User mapToUser(UserDto userDto);
}
UserDto mapToUserDto(User user);
User mapToUser(UserDto userDto);
AutoUserMapper MAPPER = Mappers.getMapper(AutoUserMapper.class);
Mapping Fields With Different Field Names
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String lastName;
@Column(nullable = false, unique = true)
private String email;
}
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
private Long id;
private String firstName;
private String lastName;
private String emailAddress;
}
@Mapper
public interface AutoUserMapper {
AutoUserMapper MAPPER = Mappers.getMapper(AutoUserMapper.class);
@Mapping(source = "email", target = "emailAddress")
UserDto mapToUserDto(User user);
@Mapping(source = "emailAddress", target = "email")
User mapToUser(UserDto userDto);
}
3. Use UserMapper in Service Class to map the JPA entity into DTO and vice versa
package net.javaguides.springboot.service.impl;
import lombok.AllArgsConstructor;
import net.javaguides.springboot.dto.UserDto;
import net.javaguides.springboot.entity.User;
import net.javaguides.springboot.mapper.AutoUserMapper;
import net.javaguides.springboot.mapper.UserMapper;
import net.javaguides.springboot.repository.UserRepository;
import net.javaguides.springboot.service.UserService;
import org.apache.logging.log4j.util.Strings;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
private ModelMapper modelMapper;
@Override
public UserDto createUser(UserDto userDto) {
// Convert UserDto into User JPA Entity
// User user = UserMapper.mapToUser(userDto);
//User user = modelMapper.map(userDto, User.class);
User user = AutoUserMapper.MAPPER.mapToUser(userDto);
User savedUser = userRepository.save(user);
// Convert User JPA entity to UserDto
//UserDto savedUserDto = UserMapper.mapToUserDto(savedUser);
//UserDto savedUserDto = modelMapper.map(savedUser, UserDto.class);
UserDto savedUserDto = AutoUserMapper.MAPPER.mapToUserDto(savedUser);
return savedUserDto;
}
@Override
public UserDto getUserById(Long userId) {
User user = userRepository.findById(userId).get();
//return UserMapper.mapToUserDto(user);
//return modelMapper.map(user, UserDto.class);
return AutoUserMapper.MAPPER.mapToUserDto(user);
}
@Override
public List<UserDto> getAllUsers() {
List<User> users = userRepository.findAll();
// return users.stream().map(UserMapper::mapToUserDto)
// .collect(Collectors.toList());
// return users.stream().map((user) -> modelMapper.map(user, UserDto.class))
// .collect(Collectors.toList());
return users.stream().map((user) -> AutoUserMapper.MAPPER.mapToUserDto(user))
.collect(Collectors.toList());
}
@Override
public UserDto updateUser(UserDto user) {
User existingUser = userRepository.findById(user.getId()).get()
existingUser.setFirstName(user.getFirstName());
existingUser.setLastName(user.getLastName());
existingUser.setEmail(user.getEmail());
User updatedUser = userRepository.save(existingUser);
//return UserMapper.mapToUserDto(updatedUser);
//return modelMapper.map(updatedUser, UserDto.class);
return AutoUserMapper.MAPPER.mapToUserDto(updatedUser);
}
@Override
public void deleteUser(Long userId) {
userRepository.deleteById(userId);
}
}
4. Test CRUD REST APIs using the Postman Client
Create User REST API:
Request Body:
{
"firstName": "ramesh",
"lastName":"fadatare",
"email": "ramesh@gmail.com"
}
Refer to this screenshot to test Create User REST API:Get User REST API:
Update User REST API:
Request Body:
{
"firstName": "ram",
"lastName":"fadatare",
"email": "ram@gmail.com"
}
Refer to this screenshot to test the Update User REST API:
Comments
Post a Comment
Leave Comment