Better Spring Data Repositories
- 6 minsSo, you find yourself having to make changes in a Java application where folks are using Spring Data based repositories. Everything looks good in the beginning, no need to implement any ORM code from scratch since Spring Data will figure that out for us. Let’s see an example.
Given the above Customer
entity, imagine you have the following repository interface:
As you may have realized, just by extending CrudRepository
you get all the basic stuff like save
, findAll
, findOne
for free. Then, anything more complex, like the two declared methods, will be interpreted by Spring Data in runtime based on name conventions.
The Problem
As time goes by and business starts to ask more complicated questions, your repository starts to get weird. The following code is an example that illustrates a real world situation I’ve faced recently:
At this point, the maintenance of this particular repository starts to become problematic for obvious reasons:
- Method names are too long and excessively verbose;
- They’re not easy to read;
- It’s not straightforward to build new queries (as we need to rely on Spring Data ability to understand the method name);
- Some method names don’t even result in a valid English sentence.
Imagine yourself talking to your pair:
Hey Akon, I think we could use the find by first name and last name and birth date is between and status in order by enrollment desc method here.
Awkward, to say the least.
Another problem that may call your attention is the duplication of criteria among the query methods: most of them are repeating the same filters over and over again. And as the amount of filters increases, the argument list also increases making it more difficult to figure out what is what.
Wouldn’t that be great if we could extract those filters in smaller reusable pieces?
JPA Specifications
With the Spring Data JPA Specifications API we can implement this idea of extracting all filter and sorting criteria in independent pieces. Let’s see how the new version of the the repository looks like:
As you can see in this new version we had to extend JpaSpecificationExecutor
. That makes it possible for our repository to accept Specification
based queries using the following method:
After that, we’ve implemented each of the necessary filters and sorting as static methods and got rid of all the old long-named methods. The inner Specifications
class works as a namespace just to avoid Spring Data trying to interpret our filters as regular CrudRepository
methods.
Without getting too deep in details about root
, query
, cb
(criteria builder), what our new methods do is to return reusable specifications. And that should be enough to allow us to replace calls to
with the following code:
The example above, alone, would be enough to make most people happy when it comes to readability and flexibility. Still, we could even go further and define default methods with meaningful names in our new repository using our new specifications like this:
Conclusion
The magic Spring Data does, allowing us to define queries only by writing method names is definitely cool for most of the simpler situations. However, it doesn’t scale well as queries become more complex. The Specification API, as described, seems to be a good alternative. Keep that in your tool-belt.