

Table of Contents
1. Overview
In this article, We will learn Spring JPA Projection example using interface and class. Projection means select only specific column instead of fetching all the columns from the table. Spring JPA provides projection using Interface as well as class.
Projection is always the good practice because selecting only specific columns will improve the performance of the application.
Here is an example of implements JPA in spring boot application, in this article, we have considered the only repository layer for more readable and clean code.
2. Spring JPA Projection using Interface
1. Close Projection
Here we have defined an interface which contains methods which are matching with properties name.
EmployeeBasicDetails.java
package com.javadeveloperzone.model; public interface EmployeeBasicDetails { String getEmployeeName(); String getEmployeeId(); }
Projection in the @Query annotation and method query
The close projection will fetch all the matching properties columns which are defined in the interface.
@Repository @Transactional public interface EmployeeDAO extends org.springframework.data.repository.Repository<Employee,Integer> { @Query("SELECT e.employeeName as employeeName,e.employeeRole as employeeRole FROM Employee e") // JPA projection using query List<EmployeeBasicDetails> getEmployeeBasicDetails(); List<EmployeeBasicDetails> findAllByEmployeeName(String name); // JPA projection using method name }
Query:
SELECT employeeId, employeeName FROM employee WHERE employeeName=?
2. Open Projection
When we used @Value annotation inside interface then it is known as open projection.
NOTE: When we used option projection then Spring JPA will fetch all the columns, It will not optimize the query by only selecting specific columns because we can use any columns in the @Value
annotation. Here are more details about open projections.
We are as define an interface and define getBasicDetails()
with @Value annotation, Inside @Value
annotation we can use any properties of Entity
not only those which are defined in the interface.
EmployeeBasicDetails.java
package com.javadeveloperzone.model; import org.springframework.beans.factory.annotation.Value; public interface EmployeeBasicDetails { String getEmployeeName(); String getEmployeeId(); @Value("#{target.employeeName + ' ' + target.employeeRole}") String getBasicDetails(); }
EmployeeDAO.java
@Repository @Transactional public interface EmployeeDAO extends org.springframework.data.repository.Repository<Employee,Integer> { List<EmployeeBasicDetails> findAllByEmployeeName(String name); }
Query:
SELECT employeeId, employeeName FROM employee WHERE employeeName=?
3. Runtime projection
Spring data JPA also support runtime projection based on pass class or interface projection will be applied.
EmployeeBasicDetails.java
package com.javadeveloperzone.model; public interface EmployeeBasicDetails { String getEmployeeName(); String getEmployeeId(); }
EmployeeNamesDetails.java
package com.javadeveloperzone.model; public interface EmployeeNamesDetails { String getEmployeeName(); }
EmployeeDAO.java
@Repository @Transactional public interface EmployeeDAO extends org.springframework.data.repository.Repository<Employee,Integer> { <T> List<T> findAllByEmployeeName(String name,Class<T> type); }
Query:
SELECT employeeId, employeeName, employeeRole FROM employee WHERE employeeName=?
Output:
employeeDAO.findAllByEmployeeName("Jone", EmployeeBasicDetails.class).forEach((v)->{ System.out.println(v.getEmployeeName()); System.out.println(v.getEmployeeId()); }); employeeDAO.findAllByEmployeeName("Jone", EmployeeNamesDetails.class).forEach((v)->{ System.out.println(v.getEmployeeName()); });
2. Spring JPA Projection using Class
While working projection using Class make sure that requires to define the proper public constructor with all the fields. Otherwise, Spring JPA will generate runtime error like : org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class
public class EmployeeBasicDetails { private final String employeeName; private final int employeeId; public EmployeeBasicDetails(int employeeId,String employeeName){ this.employeeId=employeeId; this.employeeName=employeeName; } public int getEmployeeId() { return employeeId; } public String getEmployeeName() { return employeeName; } }
EmployeeDAO.java
@Repository @Transactional public interface EmployeeDAO extends org.springframework.data.repository.Repository<Employee,Integer> { List<EmployeeBasicDetails> findAllByEmployeeName(String name); }
Query:
SELECT employeeId, employeeName FROM employee WHERE employeeName=?
3. Conclusion
In this article, we learned about different ways to apply projection in Spring Data JPA like projection using interface and class. while interface has two ways of projection: open and close projection.
1 comment. Leave new
Need more explanation about JPA Projection.