By Mandip Dhakal
When using Spring Data JPA for querying and retrieving data from the database, we can specify the repository layer to fetch only the required data instead of fetching anything and everything. To specify which attributes to select, we can use projection. Projection not only helps to select required attributes from the root entity, but also works with the nested entities that share some kind of relationship with the root entity. In this blog, we will look into the projection techniques and different ways to achieve it.
What is Projection in Spring Data JPA?
Projection is a feature in Spring Data JPA that allows us to define custom interfaces, classes or records to retrieve specific attributes from our entities. By using projection, we can fetch only the necessary data, reducing the data transferred between the database and application, resulting in improved performance.
Let’s quickly create required classes and a repository to get started. In this blog, We have an entity class called “Inventory ” which has some attributes and also has a ManyToOne relationship with the “Product” class. Whenever we try to fetch Inventory data, by default JPA tries to fetch all the attributes from the database. Now let’s see how we can use projection to fetch only those attributes that we require and even how we can manipulate the values.
Suppose we have an entity class called “Inventory” that has some relationship with another entity called “Product”:
Example 1: Projection using Interface
An interface in projection defines a custom data structure specifying the fields to be retrieved from a database query result, allowing for efficient and selective data extraction.
Example 2: Projection using a DTO
DTO (Data Transfer Object): A DTO is a plain Java object used to transfer data between different layers or components of an application.
Example 3: Projection Using a Record
Record: A record is a concise class-like construct used to represent immutable data that automatically generates methods like hashCode(), equals() and toString().
For all these three approaches, we can define a repository interface as:
In this repository, the findInventoryById() method will only query for the data that are specified in "TestResponse".
Example 4: Nested Projection
We can further fetch the attributes using a relationship as well. In the Inventory entity, there's a ManyToOne relationship with the Product entity. So, in any case if we also need Product data, then we can achieve it using the following techniques.
4.1 Using an interface:
4.2 Using a DTO Class:
4.3 Using a Record:
Now the repository will also join the Product table and query for Product Id and Product Name data.
Example 5: Open Projection
Whenever there is a need to manipulate values based on the results from the database, we can use open projection as shown below. In the below example, the "code" and "id" value will be concatenated with "-" sign in the variable "customInformation".
Conclusion:
In this blog, we've seen how we can use projection using Interfaces, DTO (Data Transfer Object) class and Records to fetch only the required data from the database. It is often used when the table contains many attributes and relationships and we only need a few of the information to perform certain operations. In this case, we can reduce the overload to the database and optimize the query.
Happy Coding!
Reference:
コメント