Lesson 3: Derived Query Methods
In this lesson, we’ll explore Spring Data JPA’s derived query methods. We'll discuss the naming convention, which is the cornerstone of this feature.
2. Lesson Notes
The relevant module you need to import when you're starting with this lesson is: derived-query-methods-start
If you want to have a look at the fully implemented lesson, as a reference, feel free to import: derived-query-methods-end
Derived queries are probably one of the most popular features of Spring Data JPA, since they significantly reduce the amount of boilerplate code that’s required at the data access layer.
Simply put, it’s a very straightforward way of defining queries by declaring interface methods in our repositories following an intuitive naming convention.
For example, in order to write a query that retrieves a Project using its code, it's enough to simply declare a method in our ProjectRepository interface:
As we can see, we don’t have to implement this method, we just have to declare it in the interface. At runtime, the framework will derive the underlying query by parsing the method name and returning an Optional object.
Let’s invoke this method from our main class:
In order to analyze the query that Spring JPA generates, we'll enable query logging by setting the appropriate property in the application.properties file:
Let’s run the app and observe the generated query in the log output:
As we can see, the query generated by Spring JPA includes a WHERE clause to filter the rows based on the code attribute value. As a result, the query returns the corresponding Project object wrapped into an Optional type.
2.2. Structure of Derived Query Methods
The query worked because the method follows a certain method naming convention supported by the framework. In this section, we’ll discuss the convention in order to get a better understanding of how it works.
First of all, the method names should follow a camel-case convention, so that the framework can parse and split the method name correctly.
The method name consists of a "subject" and a "predicate" section. The first part, find…By, defines the subject of the query, while the second part, CodeEquals, forms the predicate.
The subject part of the query primarily denotes the intent of the query. For example, find…By is a subject keyword that roughly translates to a select query.
Spring JPA supports multiple subject-introducing keywords. For instance, we can get the count of records in the query result by using the count…By keyword:
As the name implies, this method returns an integer value denoting the count of projects whose name field equals the one passed as the function argument. Let's invoke this method, and log its result:
Now we can run the application and find the corresponding query generated by Spring JPA in the console output, together with the expected message:
Notice that our query method is translated to a COUNT clause. As expected, the query returns an integer value of 1.
Among other subject keywords supported by Spring, we should mention the following ones:
For the complete list of supported keywords, you can check the reference in the Resources section.
Finally, it’s worth mentioning that the subject can include some result-limiting keywords, as well as some descriptive text. For example, let’s look at the following query methods:
In the first method, we added the DISTINCT result-limiting keyword, which affects the generated query.
In contrast, we added just descriptive text to the second method; 'BaeldungProjects' will simply be ignored by the framework, as its role is just to provide additional information about the query intent.
Anything after the first By keyword is interpreted as the predicate, and it defines the criteria of the query, containing the entity-specific conditional expressions.
We can use various condition keywords, such as Equals, Containing, GreaterThan, along with the entity’s property names to express the conditions.
For example, in the query we defined previously, we used the Equals condition applied to the code attribute of the Project: