Spring Data JPA DTO Projection Example

Using DTO (Data Transfer Object) projections in Spring Data JPA is a powerful way to select specific columns from a database, reducing the overhead of selecting unnecessary data. Here's a step-by-step guide on how to set up DTO projections using an Employee entity as an example.

1. Setting up the project

Ensure you have the necessary dependencies in your pom.xml:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
        

2. Define the Entity

Here's the Employee entity:


@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String department;
    private Double salary;

    // getters, setters, etc.
}

3. Create a DTO Projection

Suppose you want to retrieve only the firstName, lastName, and department:


public class EmployeeInfoDto {
    private final String firstName;
    private final String lastName;
    private final String department;

    public EmployeeInfoDto(String firstName, String lastName, String department) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.department = department;
    }

    // getters
}

4. Create the Repository

Define a custom query using JPQL in the repository:


public interface EmployeeRepository extends JpaRepository<Employee, Long> {

    @Query("SELECT new com.yourpackage.EmployeeInfoDto(e.firstName, e.lastName, e.department) FROM Employee e")
    List<EmployeeInfoDto> findAllEmployeeInfo();
}

The @Query selects the desired fields and maps them to the EmployeeInfoDto.

5. Use the Repository in a Service

Now, utilize the repository method in your service layer:


@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    public List<EmployeeInfoDto> getAllEmployeeInfo() {
        return employeeRepository.findAllEmployeeInfo();
    }
}

6. Test the Service

Set up a test to ensure your DTO projections work correctly:


@RunWith(SpringRunner.class)
@SpringBootTest
public class EmployeeServiceTest {

    @Autowired
    private EmployeeService employeeService;

    @Test
    public void testFetchEmployeeInfo() {
        List<EmployeeInfoDto> employeeInfo = employeeService.getAllEmployeeInfo();
        for (EmployeeInfoDto info : employeeInfo) {
            assertNotNull(info.getFirstName());
            assertNotNull(info.getLastName());
            assertNotNull(info.getDepartment());
        }
    }
}

7. Why Use DTO Projections?