Spring Boot JPA Projection (Fetching Specific Columns)

Projection in Spring Boot JPA allows you to fetch specific columns from a table instead of the entire entity. This improves performance by reducing data transfer.


Using Interface-Based Projection

The simplest way to fetch specific columns is by defining an interface projection


Example: Fetching Only id and name from User

User.java
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
private String email;
private int age;

// Getters and Setters
}

Define a Projection Interface
public interface UserProjection {
Long getId();
String getName();
}

Modify Repository to Use Projection
public interface UserRepository extends JpaRepository<User, Long> {
// Fetch only id and name
List<UserProjection> findByAgeGreaterThan(int age);
}
Fetch Data in Service Layer
@Service
public class UserService {
@Autowired
private UserRepository userRepository;

public List<UserProjection> getUsersByAge(int age) {
return userRepository.findByAgeGreaterThan(age);
}
}
Response JSON (Example)
[
{ "id": 1, "name": "John" },
{ "id": 2, "name": "Sathish" }
]

Advantage:Faster than fetching the entire entity.


Using JPQL with Projection

If you need custom queries, you can use JPQL.

Modify Repository with @Query
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u.id, u.name FROM User u WHERE u.age > :age")
List<Object[]> findUserNamesByAge(@Param("age") int age);
}
Convert Object Array in Service Layer
public List<Map<String, Object>> getUserNamesByAge(int age) {
List<Object[]> users = userRepository.findUserNamesByAge(age);
return users.stream()
.map(obj -> Map.of("id", obj[0], "name", obj[1]))
.collect(Collectors.toList());
}
Expected Response
[
{ "id": 1, "name": "John" },
{ "id": 2, "name": "Sathish" }
]

Advantage: More flexible, can handle complex queries.


Using DTO (Data Transfer Object) Projection

 Example: Fetching id, name, and age into a DTO


UserDTO.java
public class UserDTO {
private Long id;
private String name;
private int age;

public UserDTO(Long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}

// Getters
public Long getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
}
Modify Repository to Use DTO
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT new com.example.dto.UserDTO(u.id, u.name, u.age) FROM User u WHERE u.age > :age")
List<UserDTO> findUsersByAge(@Param("age") int age);
}
Service Method
public List<UserDTO> getUsersByAge(int age) {
return userRepository.findUsersByAge(age);
}
Expected Response
[
{ "id": 1, "name": "John", "age": 30 },
{ "id": 2, "name": "Sathish", "age": 28 }
]

Advantage: Works well with custom DTO transformations.


Native SQL Queries with Projection

If you need raw SQL, use @Query(nativeQuery = true).

Modify Repository for Native Query
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT id, name FROM users WHERE age > :age", nativeQuery = true)
List<Object[]> findUsersByAgeNative(@Param("age") int age);
}
Convert Object Array in Service Layer
public List<Map<String, Object>> getUsersByAgeNative(int age) {
List<Object[]> users = userRepository.findUsersByAgeNative(age);
return users.stream()
.map(obj -> Map.of("id", obj[0], "name", obj[1]))
.collect(Collectors.toList());
}
Expected Response
[
{ "id": 1, "name": "John" },
{ "id": 2, "name": "Sathish" }
]

Advantage: Ideal for complex SQL queries with joins, group by, etc.


Whereisstuff is simple learing platform for beginer to advance level to improve there skills in technologies.we will provide all material free of cost.you can write a code in runkit workspace and we provide some extrac features also, you agree to have read and accepted our terms of use, cookie and privacy policy.
© Copyright 2024 www.whereisstuff.com. All rights reserved. Developed by whereisstuff Tech.