What is a DTO?
A Data Transfer Object (DTO) is a simple Java object used to encapsulate data and transfer it between different parts of an application. DTOs are particularly useful when we want to decouple our domain entities from the data representation sent to clients, ensuring that the client only receives the necessary data.
Step-by-Step Guide
1. Setting Up the Project
First, make sure you have a Spring Boot 3 project set up. You can create a new Spring Boot project using Spring Initializr. Select the following dependencies:
- Spring Data JPA
- Spring Web
- H2 Database (for simplicity, you can choose any other database)
2. Creating the Entity
Let's create a simple Employee
entity.
package com.example.demo.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "employees")
public class Employee {
@Id
private Long id;
private String firstName;
private String lastName;
private String email;
// Getters and Setters
}
3. Defining the DTO
Next, create a DTO class that will represent the data we want to transfer.
package com.example.demo.dto;
public class EmployeeDTO {
private String firstName;
private String lastName;
private String email;
// Constructor
public EmployeeDTO(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// Getters and Setters
}
4. Writing the Native Query
Create a repository to execute the native query and map the results to the DTO.
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
@Query(value = "SELECT e.first_name AS firstName, e.last_name AS lastName, e.email AS email " +
"FROM employees e WHERE e.email = :email", nativeQuery = true)
List<Object[]> findEmployeeByEmail(@Param("email") String email);
}
5. Converting the Native Query Results to DTO
Create a service class to handle the conversion of raw query results to DTOs using constructor-based dependency injection.
package com.example.demo.service;
import com.example.demo.dto.EmployeeDTO;
import com.example.demo.repository.EmployeeRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class EmployeeService {
private final EmployeeRepository employeeRepository;
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public List<EmployeeDTO> getEmployeeByEmail(String email) {
List<Object[]> results = employeeRepository.findEmployeeByEmail(email);
return results.stream()
.map(result -> new EmployeeDTO(
(String) result[0],
(String) result[1],
(String) result[2]))
.collect(Collectors.toList());
}
}
6. Creating a REST Controller
Finally, create a REST controller to expose an endpoint for fetching the employee data.
package com.example.demo.controller;
import com.example.demo.dto.EmployeeDTO;
import com.example.demo.service.EmployeeService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class EmployeeController {
private final EmployeeService employeeService;
public EmployeeController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
@GetMapping("/employees")
public List<EmployeeDTO> getEmployeesByEmail(@RequestParam String email) {
return employeeService.getEmployeeByEmail(email);
}
}
7. Running the Application
Run your Spring Boot application and test the endpoint by navigating to http://localhost:8080/employees?email=test@example.com
with the appropriate email parameter.
Conclusion
In this blog post, we've demonstrated how to convert native query results into a DTO in a Spring Boot 3 project using constructor-based dependency injection. By following these steps, you can ensure that your application remains clean and that your clients only receive the data they need. This approach also helps in maintaining the separation of concerns and improves the overall architecture of your Spring Boot application.
Happy coding!
Comments
Post a Comment
Leave Comment