You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot接口投影分页:修改返回键名与排序方案咨询

解决方案

1. 修改_embedded节点下的键名

接口投影默认会被Spring HATEOAS序列化为tupleBackedMaps,要改成somethingElse,有两种实用方法:

方式一:给投影接口加@Relation注解

直接在你的CustomResult投影接口上标注@Relation,指定collectionRelation为目标名称:

import org.springframework.data.rest.core.annotation.Relation;

@Relation(collectionRelation = "somethingElse")
public interface CustomResult {
    // 你的投影方法示例:
    String getName();
    Integer getAge();
}

这样返回的分页结果里,_embedded下的键就会变成somethingElse。

方式二:手动构建PagedModel(更灵活)

如果不想依赖Spring Data REST的注解,可以手动将Page转换为自定义PagedModel,指定元素的关系名称:

import org.springframework.hateoas.PagedModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class YourController {

    private final YourRepository repository;

    public YourController(YourRepository repository) {
        this.repository = repository;
    }

    @GetMapping("/your-endpoint")
    public PagedModel<CustomResult> getPagedResults(@RequestParam int page, @RequestParam int size) {
        Page<CustomResult> resultPage = repository.findCustomResults(PageRequest.of(page, size));
        
        // 构建分页模型,指定collectionRelation为somethingElse
        PagedModel.PageMetadata metadata = new PagedModel.PageMetadata(size, resultPage.getNumber(), resultPage.getTotalElements());
        PagedModel<CustomResult> pagedModel = PagedModel.of(resultPage.getContent(), metadata);
        
        // 可选:添加自链接
        pagedModel.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(YourController.class).getPagedResults(page, size)).withSelfRel());
        
        return pagedModel;
    }
}

这种方式能完全掌控分页模型的结构,适合需要自定义更多细节的场景。

2. 对结果元素排序

排序有两种实现方式,按需选择:

方式一:在@Query中固定排序规则

直接在Repository的@Query注解里添加ORDER BY子句,写死排序逻辑:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;

public interface YourRepository extends PagingAndSortingRepository<YourEntity, Long> {

    @Query("SELECT c.name as name, c.age as age FROM YourEntity c ORDER BY c.name ASC")
    Page<CustomResult> findCustomResults(Pageable pageable);
}

方式二:通过Pageable参数动态控制排序

如果需要前端传递排序参数,直接利用Pageable的Sort属性即可:

// Repository层
@Query("SELECT c.name as name, c.age as age FROM YourEntity c")
Page<CustomResult> findCustomResults(Pageable pageable);

// Controller层
@GetMapping("/your-endpoint")
public PagedModel<CustomResult> getPagedResults(Pageable pageable) {
    Page<CustomResult> resultPage = repository.findCustomResults(pageable);
    // 后续处理同手动构建PagedModel的逻辑
}

前端可以通过sort=name,asc或sort=age,desc这类参数,动态指定排序字段和方向。

替代方案:转回DTO类投影(兼容你熟悉的方法)

如果接口投影限制太多,直接换回类投影就行,用你已知的RepresentationModel、@Relation和@JsonPropertyOrder实现:

import org.springframework.hateoas.RepresentationModel;
import org.springframework.data.rest.core.annotation.Relation;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@Relation(collectionRelation = "somethingElse")
@JsonPropertyOrder({"name", "age"}) // 控制字段输出顺序
public class CustomResultDTO extends RepresentationModel<CustomResultDTO> {
    private String name;
    private Integer age;

    // 构造器、getter方法
    public CustomResultDTO(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

然后Repository返回Page<CustomResultDTO>,既能通过@Relation修改_embedded的键名,又能靠@JsonPropertyOrder控制元素字段排序,完全兼容你熟悉的方案。

内容的提问来源于stack exchange,提问作者Lokesh Pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:35:29