Spring Data Rest - Sort by multiple properties
SpringSpring DataSpring Data-JpaSpring Data-RestSpring Problem Overview
I have an entity as below
Class Person{
String id;
String name;
String numberOfHands;
}
With Spring Data Rest (Gosling Release Train), I'm able to specify
localhost/Person?sort=name,asc
for sorting name name ascending. Now, in a case where I need to sort by numberOfHands descending and name ascending. I'm able to specify
localhost/Person?sort=numberOfHands,name,asc
But, I'm not able to specify
localhost/Person?sort=numberOfHands,desc,name,asc
Is there a way to specify multiple sort order?
Thanks!
Spring Solutions
Solution 1 - Spring
Solution (tl;dr)
When wanting to sort on multiple fields you simply put the sort
parameter multiple times in the URI. For example your/uri?sort=name,asc&sort=numberOfHands,desc
. Spring Data is then capable of constructing a Pageable
object with multiple sorts.
Explanation
There is not really a defined standard on how to submit multiple values for a parameter in a URI. See https://stackoverflow.com/questions/24059773/correct-way-to-pass-multiple-values-for-same-parameter-name-in-get-request.
However there is some information in the Java Servlet Spec which hints on how Java servlet containers parse request parameters.
> The getParameterValues
method returns an array of String
objects containing all the parameter values associated with a parameter name. ... - Java Servlet Spec, section 3.1
The sample further in that section states (although it mixes request and body data)
> For example, if a request is made with a query string of a=hello
and a post body of a=goodbye&a=world
, the resulting parameter set would be ordered a=hello, goodbye, world
.
This sample shows that when a parameter (a
in the example) is presented multiple times the results will be aggregated into a String[]
.
Solution 2 - Spring
Here is how to construct the multi Sort object manually/programatically.
Sort sort = Sort.by(
Sort.Order.asc("name"),
Sort.Order.desc("numberOfHands"));
return personRepository.findAll(sort);
Note: This solution does not directly solve the original question asked, but may help visitors that landed on this question while searching for a solution how to sort on multiple properties from a backend perspective / in a somewhat "hardcoded" way. (this solution does not require/take any URI parameters)
Solution 3 - Spring
When dynamic fields are there then you simply do match with fields and add in sorting list like.
List<Sort.Order> sorts= new ArrayList<>();
if (sort == "name" && sortingOrder.equalsIgnoreCase("DESC")) {
sorts.add(new Sort.Order(Sort.Direction.DESC,"name"));
} else if (sort == "numberOfHands" && sortingOrder.equalsIgnoreCase("DESC")) {
sorts.add(new Sort.Order(Sort.Direction.DESC,"numberOfHands"));
}
return personRepository.findAll(Sort.by(sorts));
If you are using Pagination then directly add in PageRequest Request.
return personRepository.findPersons(PageRequest.of(pageNo, pageSize, Sort.by(sorts)));