如何在spring-data-rest中将Page<ObjectEntity>映射为Page<ObjectDTO>

84
当我使用 PagingAndSortingRepository.findAll(Pageable) 访问数据库时,我会得到 Page<ObjectEntity>。然而,我希望向客户端公开 DTO 而不是实体。我可以通过将实体注入其构造函数来创建 DTO,但如何将 Page 对象中的实体映射为 DTO 呢?根据 Spring 文档,Page 提供只读操作。
另外,由于我们不支持 Java 8,因此不能使用 Page.map。如何手动创建包含映射对象的新 Page?

4
我不确定,但我猜您可以在不使用 lambda 表达式的情况下使用 Page.map。只需传递一个 Converter<? super T, ? extends S> 的实例即可。 - Ali Dehghani
14个回答

100

您仍然可以使用Page.map而无需使用lambda表达式:

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

4
嗨,@Ali,我不确定应该导入哪个转换器类。你能帮我解决这个疑问吗? - Martin Larizzate
1
感谢帮助阿里·德加尼。 - Martin Larizzate
1
转换器包是什么? - Dhanushka sasanka
1
@Dhanushkasasanka 可能你正在使用Spring Data 2,关于这个问题请参考https://dev59.com/1VkT5IYBdhLWcg3wG8D4#48831688 - Ali Dehghani
显示剩余2条评论

33
在Spring Data 2中,Page map方法采用了Function而不是Converter,但它的基本工作方式仍与@Ali Dehghani所描述的相同。
使用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;
    }
});

1
在这里,“Function Package”是什么? - Dhanushka sasanka

33

而在Java 8中:

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

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


2
要像 OP 请求的那样使用 DTO 构造函数,您可以使用 .map(ObjectDto::new);而不是 .map(ObjectDto::fromEntity);(这假定您在 ObjectDto 中定义了适当的构造函数)。 - java-addict301

12

您可以通过简单地执行以下步骤来使用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

我使用模型映射器、泛型和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));
} 

这正是您需要的情况(我认为也适用于其他许多情况)。

您已经通过以下方式从存储库(服务也是如此)获取了数据:

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

转换所需的一切都是通过以下方式调用此方法:

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

@提示:您可以使用util类中的此方法,并根据您的架构在服务和控制器上重新使用它以进行所有实体/DTO在页面转换中。
示例:
Page<ObjectDto> dtoPage = mapperUtil.mapEntityPageIntoDtoPage(entities, ObjectDto.class);

4

以下是我根据 @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
Page<Order> persistedOrderPage = orderQueryRepository.search();

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

3

使用Lambda表达式更加方便。

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

2

这在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中使用函数。


2

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

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


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

这里的employeeEntityToDto()方法是将实体转换为数据传输对象(DTO)的方法。

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

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