Selecting specific columns (or a subset of columns) in Spring Data JPA can be achieved using multiple ways, but one of the most common approaches is using JPQL in combination with DTO projections. In this guide, I'll demonstrate how to select specific columns using this approach.
Make sure you have the required dependencies in your pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
For this example, let's use a Person
entity:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private Date dateOfBirth;
// getters, setters, etc.
}
This DTO will represent the subset of columns we wish to retrieve. For instance, if we only want the
firstName
and lastName
:
public class PersonNameDto {
private final String firstName;
private final String lastName;
public PersonNameDto(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// getters
}
Note the final
keyword for fields and the constructor to initialize these fields.
Define a custom query using JPQL in the repository:
public interface PersonRepository extends JpaRepository<Person, Long> {
@Query("SELECT new com.yourpackage.PersonNameDto(p.firstName, p.lastName) FROM Person p")
List<PersonNameDto> findAllNames();
}
The above query selects only the firstName
and lastName
from the
Person
entity and maps them to the PersonNameDto
.
Now, you can retrieve the specific columns in your service layer:
@Service
public class PersonService {
@Autowired
private PersonRepository personRepository;
public List<PersonNameDto> getPersonNames() {
return personRepository.findAllNames();
}
}
You can create a test to ensure the specific columns are being retrieved:
@SpringBootTest
public class PersonServiceTest {
@Autowired
private PersonService personService;
@Test
public void testFetchNames() {
List<PersonNameDto> names = personService.getPersonNames();
for (PersonNameDto name : names) {
assertNotNull(name.getFirstName());
assertNotNull(name.getLastName());
}
}
}
This approach uses DTO projections to map specific columns, providing a type-safe way of retrieving partial entities.
This is useful for performance, especially when the full entity contains many columns or large content (like blobs). It's also possible to achieve similar functionality using native SQL queries, the JPA Criteria API, or other third-party libraries like Querydsl.
Always ensure that the DTO's constructor parameters match the order of columns in your custom query to ensure the correct mapping.