Spring Data Rest - Sort by multiple properties

SpringSpring DataSpring Data-JpaSpring Data-Rest

Spring 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)));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrakpanView Question on Stackoverflow
Solution 1 - SpringM. DeinumView Answer on Stackoverflow
Solution 2 - SpringBitfullByteView Answer on Stackoverflow
Solution 3 - SpringMukesh DudhatView Answer on Stackoverflow