【问题标题】:How to map Page<ObjectEntity> to Page<ObjectDTO> in spring-data-rest如何在 spring-data-rest 中将 Page<ObjectEntity> 映射到 Page<ObjectDTO>
【发布时间】:2016-12-26 11:32:20
【问题描述】:

当我用PagingAndSortingRepository.findAll(Pageable) 访问数据库时,我得到Page&lt;ObjectEntity&gt;。但是,我想向客户端而不是实体公开 DTO。我可以通过将实体注入它的构造函数来创建 DTO,但是如何将 Page 对象中的实体映射到 DTO?根据spring文档,Page提供了只读操作。

另外,Page.map 是不可能的,因为我们不支持 java 8。如何手动创建带有映射对象的新页面?

【问题讨论】:

  • 我不确定,但我猜你可以在没有 lambda 表达式的情况下使用 Page.map。只需传递Converter&lt;? super T, ? extends S&gt; 的实例

标签: java spring spring-mvc spring-data spring-data-rest


【解决方案1】:

您仍然可以在没有 lambda 表达式的情况下使用 Page.map

Page<ObjectEntity> entities = objectEntityRepository.findAll(pageable);
Page<ObjectDto> dtoPage = entities.map(new Converter<ObjectEntity, ObjectDto>() {
    @Override
    public ObjectDto convert(ObjectEntity entity) {
        ObjectDto dto = new ObjectDto();
        // Conversion logic

        return dto;
    }
});

【讨论】:

【解决方案2】:

感谢@Ali Dehghani,这是我的解决方案

private Page<ObjectDTO> mapEntityPageIntoDTOPage(Page<ObjectEntity> objectEntityPage) {
        return objectEntityPage.map(new Converter<ObjectEntity, ObjectDTO>() {
            public ObjectDTO convert(ObjectEntity objectEntity) {
                return new ObjectDTO(objectEntity, httpSession);
            }

        });
    }

【讨论】:

    【解决方案3】:

    在 java8 中:

    Page<ObjectDto> entities = 
     objectEntityRepository.findAll(pageable)
     .map(ObjectDto::fromEntity);
    

    其中 fromEntity 是 ObjectDto 上包含转换逻辑的静态方法。

    【讨论】:

    • 要使用 OP 请求的 DTO 构造函数,您可以使用 .map(ObjectDto::new);而不是 .map(ObjectDto::fromEntity); (这假设您在 ObjectDto 中定义了正确的构造函数)
    【解决方案4】:

    在 Spring Data 2 中,Page map 方法采用 Function 而不是 Converter,但它仍然与 @Ali Dehghani 描述的基本相同。

    使用功能:

    Page<ObjectEntity> entities = objectEntityRepository.findAll(pageable);
    Page<ObjectDto> dtoPage = entities.map(new Function<ObjectEntity, ObjectDto>() {
        @Override
        public ObjectDto apply(ObjectEntity entity) {
            ObjectDto dto = new ObjectDto();
            // Conversion logic
    
            return dto;
        }
    });
    

    【讨论】:

    • 这里的函数包是什么?
    【解决方案5】:

    最后,您不会将页面返回给用户,而是返回一个 ObjectDTO 列表,标题中包含页面详细信息,所以这将是我的解决方案。

    对象服务

    public Page<ObjectEntity> findAll (Pageable pageable){
      //logic goes here.
      Page<ObjectEntity> page = objectRepository.findAll(pageable);
      return page;
    } 
    

    ObjectResource / rest(暴露的端点)

    @GetMapping
    public ResponseEntity<List<ObjectDTO>> findAll (Pageable pageable){
      Page<ObjectEntity> page = objectServiceService.findAll(pageable);
    
      HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "your-endpoint-here");
    
      return new ResponseEntity<>(objectMapper.toDto(page.getContent()), headers, HttpStatus.OK);
    }
    

    使用它的原因是您不需要复制 ObjectEntity 和 DTO 的页面详细信息。需要注意的是,一个页面包含以下内容:

    • 页码
    • 页面大小
    • 元素数量
    • 内容

    content是返回的对象列表,是唯一需要映射到DTO的东西。

    【讨论】:

      【解决方案6】:

      您只需执行以下操作即可使用 Page.map:

      public Page<ObjectDto> toPageObjectDto(Page<Object> objects) {
          Page<ObjectDto> dtos  = objects.map(this::convertToObjectDto);
          return dtos;
      }
      
      private ObjectDto convertToObjectDto(Object o) {
          ObjectDto dto = new ObjectDto();
          //conversion here
          return dto;
      }
      

      【讨论】:

        【解决方案7】:

        我创建并使用具有模型映射器、泛型和 lambdas 的解决方案以供常用。

        /**
         * Maps the Page {@code entities} of <code>T</code> type which have to be mapped as input to {@code dtoClass} Page
         * of mapped object with <code>D</code> type.
         *
         * @param <D> - type of objects in result page
         * @param <T> - type of entity in <code>entityPage</code>
         * @param entities - page of entities that needs to be mapped
         * @param dtoClass - class of result page element
         * @return page - mapped page with objects of type <code>D</code>.
         * @NB <code>dtoClass</code> must has NoArgsConstructor!
         */
        public <D, T> Page<D> mapEntityPageIntoDtoPage(Page<T> entities, Class<D> dtoClass) {
            return entities.map(objectEntity -> modelMapper.map(objectEntity, dtoClass));
        } 
        

        这正是您需要的情况(我认为其他情况的常见情况)。

        您已经通过这种方式从存储库中获得了数据(服务也是如此):

        Page<ObjectEntity> entities = objectEntityRepository.findAll(pageable);
        

        转换所需的一切就是以这种方式调用此方法:

        Page<ObjectDto> dtoPage = mapEntityPageIntoDtoPage(entities, ObjectDto.class);
        

        @Tip:您可以从 util 类中使用此方法,并且可以根据您的架构在服务和控制器上的页面转换中将其重用于所有实体/dto。

        例子:

        Page<ObjectDto> dtoPage = mapperUtil.mapEntityPageIntoDtoPage(entities, ObjectDto.class);
        

        【讨论】:

          【解决方案8】:

          使用lambda表达式更方便

          Page<ObjectDto> dto=objectRepository.findAll(pageable).map((object -> DozerBeanMapperBuilder.buildDefault().map(object, ObjectDto.class)));
          

          【讨论】:

            【解决方案9】:

            这在 Spring 2.0 中可以正常工作 -

            @Override
            public Page<BookDto> getBooksByAuthor(String authorId, Pageable pageable) {
                    Page<BookEntity> bookEntity = iBookRepository.findByAuthorId(authorId, pageable);
                    return bookEntity.map(new Function<BookEntity, BookDto>() {
            
                        @Override
                        public BookDto apply(BookEntity t) {
                            return new ModelMapper().map(t, BookDto.class);
                        }
            
                    });
                }
            

            Spring 2.0 的页面类型不再支持转换器。另外,函数应该从 java.util.function.Function 中使用。

            【讨论】:

              【解决方案10】:

              使用 Java 8 Lambda,它对我有用。上面已经给出了答案,我只是在简化。

              Page<EmployeeEntity> employeeEntityPage = employeeService.findEmployeeEntities();
              
              
              Page<EmployeeDto> employeeDtoPage = employeeEntityPage.map(entity -> {
                      EmployeeDto dto = employeeService.employeEntityToDto(entity);
                      return dto;
                  });
              

              这里的employeeEntityToDto()是Entities转Dtos的方法

              public EmployeeDto employeeEntityToDto(EmployeeEntity entity){
                  EmployeeDto employeeDto =  new EmployeeDto();
                  employeeDto.setId(entity.getId());
                  employeeDto.setName(entity.getName());
                  return employeeDto;
              }
              

              【讨论】:

                猜你喜欢
                • 2023-03-05
                • 1970-01-01
                • 2023-03-26
                • 2020-01-26
                • 2020-06-27
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-01-20
                相关资源
                最近更新 更多