多重排序可选查询 - 使用分页的Spring REST控制器配置

12

我想构建一个可以处理多个可选排序查询的Spring控制器。根据spring.io规范,这些查询应该按照以下格式进行格式化。

&sort=name,desc&sort=code,desc

EduardoFernandes所讨论的

我知道可以使用一个实例的排序值和单独给出方向来完成,如Gregg所述,但这与Spring规范不符合,也无法处理多个排序值。

我不确定如何将多个按Spring规范格式的查询转换为Sort,然后将其传递给我的PageRequest,再传递给我的存储库。此外,如果需要使用默认值来实现可选项,最好能够使用基于注解的配置,如Rasheed Amir(@SortDefault)。

以下是我正在处理的基本内容...

领域

    @Entity
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class Subject {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
        private String code; 
    ...

存储库

    public interface SubjectRepository extends JpaRepository<Subject, Long> {
    }

服务

    @Override
    public Page<SubjectDTO> listSubjectsPageble(PageRequest pageableRequest) {
        return subjectRepository.findAll(pageableRequest)
                .map(subjectMapper::subjectToSubjectDTO);
    }

控制器

    @GetMapping
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasRole('LECTURER')")
    public Page<SubjectDTO> getSubjects(
            @RequestParam("page") int page,
            @RequestParam("size") int size,
            @RequestParam("sort") String sort
    
    ) {
    
        return subjectService.listSubjectsPageble(PageRequest.of(page, size, new Sort(sort)));
    }

所以在控制器中,我不知道如何处理或填充来自RequestParam的Sort参数。根据Ralph的说法,我应该能够使用类似下面的方法从一个参数中获取多个值,但是我不知道如何将其传递给Sort。
我知道Sort可以接受多个参数,但只能有一个排序方向。当然,我希望它们是可选的。
    @RequestParam MultiValueMap<String, String> params

请帮忙,我还是个新手 :) 谢谢
编辑:
通过Dullimeister的帖子,我解决了一些问题。但是这种方法感觉有点凌乱,而且仍然不能处理多个排序参数。有没有人知道更好的方法,或者这就是正确的方式?
    @GetMapping
        @ResponseStatus(HttpStatus.OK)
        @PreAuthorize("hasRole('LECTURER')")
        public Page<SubjectDTO> getSubjects(
                @RequestParam(value = "page", defaultValue = "0", required = false) int page,
                @RequestParam(value = "size", defaultValue = "10", required = false) int size,
                @RequestParam(value = "sort", defaultValue = "name,ASC", required = false) String sortBy
    
        ) {
            String[] sort = sortBy.split(",");
            String evalSort = sort[0];
            String sortDirection = sort[1];
            Sort.Direction evalDirection = replaceOrderStringThroughDirection(sortDirection);
            Sort sortOrderIgnoreCase = Sort.by(new Sort.Order(evalDirection,evalSort).ignoreCase());
    
            return subjectService.listSubjectsPageble(PageRequest.of(page, size, sortOrderIgnoreCase));
        }
    
        private Sort.Direction replaceOrderStringThroughDirection(String sortDirection) {
            if (sortDirection.equalsIgnoreCase("DESC")){
                return Sort.Direction.DESC;
            } else {
                return Sort.Direction.ASC;
            }
        }

最终解决方案 谢谢大家,这就是我最后得到的结果。不确定是否完美,但它能够正常工作 :) 我不得不将逗号替换为分号,因为FormattingConversionService自动将单个排序参数解析为字符串而不是String[]。
    @GetMapping
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasRole('LECTURER')")
    public Page<SubjectDTO> getSubjects(
            @RequestParam(value = "page", defaultValue = "0", required = false) int page,
            @RequestParam(value = "size", defaultValue = "10", required = false) int size,
            @RequestParam(value = "sort", defaultValue = "name;ASC", required = false) String[] sortBy) {
        Sort allSorts = Sort.by(
            Arrays.stream(sortBy)
                    .map(sort -> sort.split(";", 2))
                    .map(array ->
                            new Sort.Order(replaceOrderStringThroughDirection(array[1]),array[0]).ignoreCase()
                    ).collect(Collectors.toList())
        );

        return subjectService.listSubjectsPageble(PageRequest.of(page, size, allSorts));
    }

    private Sort.Direction replaceOrderStringThroughDirection(String sortDirection) {
        if (sortDirection.equalsIgnoreCase("DESC")){
            return Sort.Direction.DESC;
        } else {
            return Sort.Direction.ASC;
        }
    }
1个回答

12

你的控制器为什么不使用Pageable

Pageable可以处理多个排序查询,每个查询都将存储在订单列表中。 此外,任何Pageable参数都不是必需的。当你在URL中不传递它们时,Pageable将包含默认值(page=0,size=20)。你可以使用@PageableDefault注释更改默认值。

GET .../test?sort=name,desc&sort=code,desc 进入图像描述


谢谢您的回复。实现一个Pageable的唯一方法不是使用PageRequest吗?据我所知,没有超过一个排序的构造函数?(Pageable - Rinus van Heerden
是的,pageable 总是只包含一个排序,但在该排序中,您可以有多个顺序。 - Mateusz Jaszewski
好的,现在有一个问题是当我尝试从@RequestParam中获取多个排序字符串时,我希望它成为一个集合以便对其进行流处理。然而,格式$sort="id,asc"会被逗号分隔成单独的行,即@RequestParam(value = "sort", defaultValue = "name,ASC", required = false) List<String> sortBy中的数组。 - Rinus van Heerden
我想在这里进行流式处理,以构建所有“订单”的排序,如下所示:Sort allSorts = Sort.by( sortBy.stream() .map(sort -> sort.split(",", 2)) .map(array -> new Sort.Order(replaceOrderStringThroughDirection(array[0]),array[1]).ignoreCase() ).collect(Collectors.toList()) ); - Rinus van Heerden
但是sortBy返回的是sortBy0=' "id" 和 sortBy1="ASC" ',而不是应该是sortBy0= "id,asc"。 - Rinus van Heerden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接