Notice that we added required = false
inside our previous @RequestParam
annotation. This allows us to optionally add more query parameters if the user would like to search by a different field value instead. For example, we could extend the PersonRepository
interface with another method:
List<Person> findByAgeLessThan(Integer age);
and update the searchPeople
method accordingly:
@GetMapping("/people/search") public List<Person> searchPeople( @RequestParam(name = "eyeColor", required = false) String eyeColor, @RequestParam(name = "maxAge", required = false) Integer maxAge ) { if (eyeColor != null) { return this.personRepository.findByEyeColor(eyeColor) } else if (maxAge != null) { return this.personRepository.findByAgeLessThan(maxAge); } else { return new ArrayList<>(); } }
You can get even more advanced using And
queries, so that you could query the PEOPLE
table by both eyeColor
and maxAge
at the same time. The new method declaration in the interface would look like:
List<Person> findByEyeColorAndAgeLessThan(String eyeColor, Integer age);
The updated searchPeople
method would look like:
@GetMapping("/people/search") public List<Person> searchPeople( @RequestParam(name = "eyeColor", required = false) String eyeColor, @RequestParam(name = "maxAge", required = false) Integer maxAge ) { if (eyeColor != null && maxAge != null) { return this.personRepository.findByEyeColorAndAgeLessThan(eyeColor, maxAge); } else if (eyeColor != null) { return this.personRepository.findByEyeColor(eyeColor); } else if (maxAge != null) { return this.personRepository.findByAgeLessThan(maxAge); } else { return new ArrayList<>(); } }
As you can tell by now, Spring Data JPA’s CrudRepository
is a lot more powerful than it initially lets on!
The naming of the method declarations is extremely important here. The rules for the method names are detailed in the Spring documentation here.
Review the rules before proceeding to implement some custom query methods for the plant application in this exercise.
Instructions
Add the following custom query method declarations to the PlantRepository
interface.
- A query that yields a list of all plants that do NOT have fruit
- A query that yields a list of all plants that have a quantity less than a supplied parameter
quantity
- A query that yields a list of all plants that have fruit AND the quantity is less than a supplied parameter
quantity
- A query that yields a list of all plants that DO NOT have fruit AND quantity less than a supplied parameter
quantity
Try declaring them based off of the naming conventions that are detailed in the Spring Data JPA query methods documentation. If you get stuck, take a look at the hint.
Now that you have extended the capability of the PlantRepository
significantly, you should use all the new functionality in a search endpoint!
Edit your @GetMapping
method in your PlantController
. searchPlants
should return a List<Plant>
and should accept two query parameters:
@RequestParam(name="hasFruit", required=false) Boolean hasFruit, @RequestParam(name="maxQuantity", required=false) Integer quantity
For now, leave your method body as it is.
Now that your handler method, searchPlants
, is ready with the required annotations and parameters, try adding in the logic to conditionally query the database.
- If both
hasFruit
andquantity
are non-null, andhasFruit
is true, you should call thefindByHasFruitTrueAndQuantityLessThan
method. - If both
hasFruit
andquantity
are non-null, andhasFruit
is false, you should call thefindByHasFruitFalseAndQuantityLessThan
method. - If
hasFruit
is non-null, andhasFruit
is true, you should call thefindByHasFruitTrue
method. - If
hasFruit
is non-null, andhasFruit
is false, you should call thefindByHasFruitFalse
method. - If
quantity
is non-null, you should call thefindByQuantityLessThan
method. - If none of the above
if
statements pass, you should simply return an empty list withreturn new ArrayList<>();
Time to test out your fancy new search endpoint! Try the curl
commands below to see the different search results.
curl "localhost:4001/plants/search?hasFruit=false&maxQuantity=20" curl "localhost:4001/plants/search?hasFruit=false" curl "localhost:4001/plants/search?hasFruit=true" curl "localhost:4001/plants/search?hasFruit=true&maxQuantity=10" curl "localhost:4001/plants/search?maxQuantity=10"
As a reminder,
@RequestParam
is case-sensitive.hasFruit=true
will work buthasfruit=true
will not.
If, at any point, you see an error like “Failed to connect to localhost port 4001: Connection refused”, your Spring server may be malfunctioning. Fix all errors in your code, and run your code before executing the command
pkill ein
in the terminal to reset the server. Your browser will disconnect and reconnect to Codecademy.