Data Transfer Object(DTO) using ModelMapper.
Using ModelMapper, we map entity properties to various DTO classes based on the use case.
Data Transfer Object(DTO) using ModelMapper.
Using ModelMapper, we map entity properties to various DTO classes based on the use case.
1. Controller
@RestController
@RequestMapping("/api/v1/employees")
public class EmployeeController {
@Autowired
private IEmployeeService employeeService;
@Operation(summary = "Register a new employee",
description = "Registers a new employee with the provided details.")
@PostMapping
public ResponseEntity<EmployeeResponseDTO> createEmployee(
@Valid @RequestBody EmployeeRequestDTO dto) {
return new ResponseEntity<>(employeeService.createEmployee(dto), HttpStatus.CREATED);
}
@Operation(summary = "Get employee by ID",
description = "Retrieves the details of an employee by their ID.")
@GetMapping("/{id}")
public ResponseEntity<EmployeeResponseDTO> getEmployee(
@PathVariable Long id) {
return new ResponseEntity<>(employeeService.getEmployee(id), HttpStatus.OK);
}
@Operation(summary = "Get all employees",
description = "Retrieves a list of all employees with their summary details.")
@GetMapping
public ResponseEntity<List<EmployeeSummaryDTO>> getAllEmployees() {
return new ResponseEntity<>(employeeService.getAllEmployees(), HttpStatus.OK);
}
}
2. Service
/**
* Service implementation for managing Employee entities using ModelMapper for DTO conversions.
*/
@Service
public class EmployeeServiceImpl implements IEmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private EmployeeMapper mapper;
@Override
public EmployeeResponseDTO createEmployee(EmployeeRequestDTO dto) {
// Map EmployeeRequestDTO to Employee entity using ModelMapper
Employee employee = mapper.mapToEntity(dto);
// Set the date of joining to the current date
employee.setDateOfJoining(java.time.LocalDate.now());
// Save the employee entity to the database
Employee saved = employeeRepository.save(employee);
// Map the saved Employee entity to EmployeeResponseDTO using ModelMapper
return mapper.mapToResponseDTO(saved);
}
@Override
public EmployeeResponseDTO getEmployee(Long id) {
// Retrieve the employee entity from the database
Employee employee = employeeRepository.findById(id)
.orElseThrow(() ->
new EmployeeNotFoundException("Employee with id " + id + " not found"));
// Map the retrieved Employee entity to EmployeeResponseDTO using ModelMapper
return mapper.mapToResponseDTO(employee);
}
@Override
public List<EmployeeSummaryDTO> getAllEmployees() {
// Retrieve all employee entities from the database
List<Employee> employees=employeeRepository.findAll();
// Map the list of Employee entities to a list of EmployeeSummaryDTOs using ModelMapper
return mapper.mapToSummaryDTO(employees);
}
}
3. Mapper
// This class is responsible for mapping between Employee entities and various DTOs using ModelMapper.
@Component
public class EmployeeMapper {
@Autowired
private ModelMapper modelMapper;
// For mapping EmployeeRequestDTO to Employee
public Employee mapToEntity(EmployeeRequestDTO dto) {
return modelMapper.map(dto, Employee.class);
}
// For mapping Employee to EmployeeResponseDTO
public EmployeeResponseDTO mapToResponseDTO(Employee emp) {
return modelMapper.map(emp, EmployeeResponseDTO.class);
}
// For mapping List<Employee> to List<EmployeeSummaryDTO>
public List<EmployeeSummaryDTO> mapToSummaryDTO(List<Employee> emps) {
return emps.stream()
.map(emp -> modelMapper.map(emp, EmployeeSummaryDTO.class))
.toList();
}
}
Field Customization:
When the Entity property name differs in the DTO, we perform field customisation to map it.
Entity class property name and DTO are referred to as employeeName, then we have to map name → employeeName.
We use a separate Configuration class(ModelMapperConfig) along with an entity-specific mapper class (EmployeeMapper) for a cleaner enterprise approach.
// This class is responsible for configuring the ModelMapper bean used for mapping between entities and DTOs.
@Configuration
public class ModelMapperConfig {
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
// Configure ModelMapper to enable field matching and set field access level to private
modelMapper.getConfiguration()
// Enable field matching to allow mapping between fields with the same name
.setFieldMatchingEnabled(true)
// Set field access level to private to allow ModelMapper to access private fields directly
.setFieldAccessLevel(AccessLevel.PRIVATE);
// Custom mapping for Employee to EmployeeResponseDTO
modelMapper.typeMap(Employee.class, EmployeeResponseDTO.class)
.addMappings(mapper -> {
// Example of custom mapping: mapping 'name' field in Employee to 'empName' in EmployeeResponseDTO
mapper.map(Employee::getName,
EmployeeResponseDTO::setEmpName);
// Example of custom mapping: mapping 'department' field in Employee to 'empDepartment' in EmployeeResponseDTO
mapper.map(Employee::getDepartment,
EmployeeResponseDTO::setEmpDepartment);
// More custom mappings can be added here
});
return modelMapper;
}
}
Note:
ModelMapperConfig is for field customization.
EmployeeMapper for mapping Entity to DTO and vice versa.
3. Repository
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
4. Entity
@Entity
@Table(name = "EMPLOYEE_DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Column(unique = true)
private String email;
private String department;
private Double salary;
private String password;
private LocalDate dateOfJoining;
@CreationTimestamp
private LocalDateTime createdAt;
@UpdateTimestamp
private LocalDateTime updatedAt;
}
5. DTO
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EmployeeRequestDTO {
@NotBlank(message = "Name is mandatory")
private String name;
@Email(message = "Email should be valid")
@NotBlank(message = "Email is mandatory")
private String email;
@NotBlank(message = "Department is mandatory")
private String department;
@Positive(message = "Salary must be positive")
private Double salary;
@Size(min = 6, message = "Password must be at least 6 characters long")
private String password;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EmployeeResponseDTO {
private Long id;
private String name;
// To demonstrate field customization
// comment name property and use employeename
// private Strign employeeName;
private String email;
private String department;
private LocalDate dateOfJoining;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EmployeeSummaryDTO {
private Long id;
private String name;
private String email;
}
메타데이터
- post_id
- fd55cc8d79e7
- slug
- data-transfer-object-dto-using-modelmapper-fd55cc8d79e7
- url
- https://medium.com/@nazeersd.java/data-transfer-object-dto-using-modelmapper-fd55cc8d79e7
- canonical_url
- https://medium.com/@nazeersd.java/data-transfer-object-dto-using-modelmapper-fd55cc8d79e7
- author_url
- https://medium.com/@nazeersd.java
- status
- ok
- fetched_at
- 2026-06-11 05:11:55