简体   繁体   English

如何到map页面<objectentity>到页面<objectdto>在春季数据休息</objectdto></objectentity>

[英]How to map Page<ObjectEntity> to Page<ObjectDTO> in spring-data-rest

When I hit the database with PagingAndSortingRepository.findAll(Pageable) I get Page<ObjectEntity> .当我使用PagingAndSortingRepository.findAll(Pageable)访问数据库时,我得到了Page<ObjectEntity> However, I want to expose DTO's to the client and not entities.但是,我想将 DTO 公开给客户端而不是实体。 I can create DTO just by injecting entity into it's constructor, but how do I map the entities in Page object to DTO's?我可以通过将实体注入它的构造函数来创建 DTO,但是我如何将页面 object 中的实体 map 添加到 DTO? According to spring documentation, Page provides read-only operations.根据spring文档,Page提供了只读操作。

Also, Page.map is not possibility, as we don't have support for java 8. How to create the new Page with mapped objects manually?另外,Page.map 是不可能的,因为我们不支持 java 8. 如何手动创建带有映射对象的新页面?

You can still use the Page.map without lambda expressions:您仍然可以在没有 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;
    }
});

In Spring Data 2, the Page map method takes a Function instead of a Converter, but it still works basically the same as @Ali Dehghani described.在 Spring Data 2 中,Page map 方法采用 Function 而不是 Converter,但它的工作方式与 @Ali Dehghani 描述的基本相同。

Using Function:使用功能:

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

And in java8:在java8中:

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

Where fromEntity is a static method on ObjectDto that contains the conversion logic.其中 fromEntity 是 ObjectDto 上包含转换逻辑的静态方法。

You can use Page.map by simply doing this:您可以通过简单地执行以下操作来使用 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;
}

Here is my solution, thanks to @Ali Dehghani这是我的解决方案,感谢@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);
            }

        });
    }

I am created and using solution with model mapper, generics and lambdas for common usage.我创建并使用带有模型映射器、泛型和 lambda 的解决方案以供常见用途。

/**
 * 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));
} 

This is exactly the case which you need (and I think common case for wide range of other cases).这正是您需要的情况(我认为是其他各种情况的常见情况)。

You already have the data obtained from repository (same is with service) on this way:您已经通过这种方式从存储库(与服务相同)获得了数据:

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

Everything what you need for conversion is to call this method on this way:转换所需的一切就是以这种方式调用此方法:

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

@Tip: You can use this method from util class, and it can be reused for all entity/dto in Page conversions on services and controllers according to your architecture. @提示:您可以在 util 类中使用此方法,并且可以根据您的架构在服务和控制器上的页面转换中将其重用于所有实体/dto。

Example:示例:

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

This works correctly in Spring 2.0 -这在 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);
            }

        });
    }

The converter is no longer supported in Page type for Spring 2.0. Spring 2.0 的页面类型不再支持转换器。 Also, the Function should be used from java.util.function.Function.此外,函数应该从 java.util.function.Function 使用。

使用 lambda 表达式更方便

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

Page<OrderDTO> orderPage = persistedOrderPage.map(persistedOrder -> {
    OrderDTO order = mapper.toOrderDTO(persistedOrder);
    // do another action
    return order;
});

At the end, you will not return the Page to the users, but a list of ObjectDTO, with the Page details at the header, so this would be my solution.最后,您不会将页面返回给用户,而是返回一个 ObjectDTO 列表,页面详细信息位于标题处,因此这将是我的解决方案。

ObjectService对象服务

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

ObjectResource / rest (the exposed endpoint) 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);
}

The reason for using this is so that you don't need to duplicate the page details for ObjectEntity and DTO.使用它的原因是您不需要复制 ObjectEntity 和 DTO 的页面详细信息。 It is key to note that a page contains the following:需要注意的是,页面包含以下内容:

  • page number页码
  • pageSize页面大小
  • numberOfElements元素数
  • content内容

The content is the list of objects returned, and is the only thing that needs to be mapped to DTO.内容是返回的对象列表,是唯一需要映射到 DTO 的内容。

Using Java 8 Lambda ,It worked for me.使用 Java 8 Lambda,它对我有用。 The answer is already given above,I am just simplifying.上面已经给出了答案,我只是在简化。

Page<EmployeeEntity> employeeEntityPage = employeeService.findEmployeeEntities();


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

Here employeeEntityToDto() is a method to convert Entities to Dtos这里employeeEntityToDto()是一种将Entities转换为Dtos的方法

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

It's a too late answer, but this solution worked for me这是一个为时已晚的答案,但这个解决方案对我有用

Service服务

public Page<EntityDto> getAllEntities(Pageable pageable) {
    return entityRepository.findAll(pageable).map(entityMapper::toEntityDto);
}

Mapper映射器

import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface EntityMapper {
    EntityDto toEntityDto(Entity entity);
}

Controller Controller

@GetMapping(path = "/entities")
    public List<EntityDto> getAllEntities(Pageable pageable) {
        Page<EntityDto> page = entityService.getAllEntities(pageable);
        return page.getContent();
    }

this will return a list of entities with size = 10 from the first page这将从第一页返回大小 = 10 的实体列表

http://localhost:port/api/entities?page=0&size=10

Thanks to JHipster!感谢 JHipster!

I've used Lambda with ModelMapper我用 Lambda 和ModelMapper

    Page<ObjectEntity> pageEntity = objectRepository.findAll(pageable);
    Page<ObjectDto> pageDto = pageEntity.map(objectEntity -> modelMapper.map(objectEntity, ObjectDto.class));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM