【问题标题】:Spring Pageable sorting is exposing internal naming of daoSpring Pageable 排序暴露了 dao 的内部命名
【发布时间】:2019-05-28 22:30:15
【问题描述】:

我正在使用 Spring 和 Spring 存储库构建 rest 微服务。我想让客户端控制分页和排序(使用 spring-data-rest)。

public PagedResources<TestDto> find(
    @PageableDefault(page = 0, size = 50) final Pageable pageable,
    final PagedResourcesAssembler<Test> assembler) {

    final Page<Test> pagedResults = testRepository.findAll(pageable);

    return assembler.toResource(pagedResults, testResourceAssembler);
}

上面的代码效果很好,除了我不高兴排序耦合到我的 dao 层而不是 dto 层。示例:

http://localhost:8080/my-service/test?size=100&page=0&sort=statusCode,asc

json 响应(DTO):

{
  "links": [
    ...
    ...
  ],
  "content": [
    {
      "id": 4
      "status": "OK"
      "links": []
    }
  ],
  "page": {
    "size": 100,
    "totalElements": 1,
    "totalPages": 1,
    "number": 0
  }
}

请注意请求 url 中的 'statusCode' 排序与响应 dto 中相应的 'status' 之间的区别。从客户的角度来看,这是不合逻辑的。现在我也暴露了该服务的一些内部信息。我无法更改服务的实现,因为它可以被客户端使用,并且在更改名称后会破坏旧请求。

当我添加自定义映射来处理搜索请求中的状态码与状态差异时:

private PageRequest getPageRequest(final Pageable pageable) {
    final List<Order> newOrder = new ArrayList<>();
    for (final Order order : pageable.getSort()) {
    if (daoToJpaMapping.containsKey(order.getProperty())) {
            newOrder.add(new Order(order.getDirection(), daoToJpaMapping.get(order.getProperty())));
        } else {
            throw new OngeldigSortProperty(order.getProperty() + " is niet toegestaan als sorteerproperty");
        }
    }
    final PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(newOrder));

    return pageRequest;
}

它对我的 hal 响应适得其反,因为它包含基于 jpa 名称的完整 url:

{
  "links": [
    {
      "rel": "first",
      "href": "http://localhost:8080/my-service/test?page=0&size=100&sort=statusCode,asc",
...

除了自定义排序、页面和大小参数外,我找不到解决此问题的方法。但是构建一个与 spring 版本一样好用的自定义排序属性感觉就像再次发明轮子。这是否意味着我试图滥用弹簧功能?使用 DTO 是相当普遍的,所以我很惊讶没有(春季)教程解释你的休息界面中的分页涵盖这部分。有解决办法吗?

【问题讨论】:

    标签: java spring-data-jpa dao spring-data-rest dto


    【解决方案1】:

    我在我的项目中遇到了同样的问题,并通过完全分离控制器和数据层来解决它:

    控制器层对象:

    public class QueryOptionsDTO {
      int pageNumber;
      int pageSize;
      String sortField;
      String sortDirection
    
      public Pageable toPageable() {
        Sort sort = Sort.by(sortField);
        if (sortDirection.equals("asc")) {
          sort = sort.ascending();
        } else {
          sort = sort.descending();
        }
        return PageRequest.of(pageNumber, pageSize, sort);
      }
    }
    
    public class ResultPageDTO<YourObjectDTO> {
      List<YourObjectDTO> results;
      int pageNumber;
      int pageSize;
      int totalPages;
      int totalSize;
    
      public <YourDomainObject> ResultPageDTO<YourObjectDTO> from(Page page, Function<YourDomainObject, YourObjectDTO> mapper) {
        // Custom logic to map to ResultPageDTO<YourObjectDTO>
      }
    }
    
    @GetMapping
    public ResultPageDTO<YourObjectDTO> find(@RequestParam QueryOptionsDTO queryOptionsDTO) {
    
        PageResult<YourObject> pagedResults = objectQueryService.find(queryOptionsDTO.toPageable());
    
        return ResultPageDTO.of(pagedResults);
    }
    

    这是伪代码,只是为了向您展示如何实现它。

    【讨论】:

    • 您好,在您的解决方案中,DTO columnName 到 DAO columName 的映射是如何完成的?
    猜你喜欢
    • 2019-05-14
    • 1970-01-01
    • 2019-04-09
    • 2010-11-26
    • 1970-01-01
    • 2010-10-13
    • 2020-08-22
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多