Spring Data Rest- 按多个属性排序

我有一个实体如下

Class Person{
String id;
String name;
String numberOfHands;
}

通过 Spring Data Rest (Gosling Release Train) ,我可以指定

localhost/Person?sort=name,asc

用于对名称升序排序。现在,在这种情况下,我需要按照 numberOfhands 降序和名称升序进行排序。我可以详细说明

localhost/Person?sort=numberOfHands,name,asc

但是,我不能确定

localhost/Person?sort=numberOfHands,desc,name,asc

是否有指定多个排序顺序的方法?

谢谢!

109217 次浏览

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 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[].

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)

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