【问题标题】:How to call MapStruct method from interface in java stream如何从java流中的接口调用MapStruct方法
【发布时间】:2019-12-27 11:39:52
【问题描述】:

我最近开始在一个项目中使用 MapStruct 映射工具。过去,为了映射 DTO -> 实体,反之亦然,我使用自定义映射器,例如:

public static CustomerDto toDto(Customer customer) {

    return isNull(customer)
        ? null
        : CustomerDto.builder()
            .id(customer.getId())
            .name(customer.getName())
            .surname(customer.getSurname())
            .phoneNumber(customer.getPhoneNumber())
            .email(customer.getEmail())
            .customerStatus(customer.getCustomerStatus())
            .username(customer.getUsername())
            .NIP(customer.getNIP())
            .build();
  }

如果我试图获得一个 Optional 对象,毕竟我能够通过以下方式将我的实体映射到 dto:

public Optional<CustomerDto> findOneById(final long id) {
    return customerRepository.findById(id).map(CustomerMapper::toDto);
  }

目前,正如我之前提到的,我正在使用 mapStruct,问题是我的映射器不是类,它的接口如下:

@Mapper
public interface CommentMapper {

  @Mappings({
      @Mapping(target = "content", source = "entity.content"),
      @Mapping(target = "user", source = "entity.user")
  })
  CommentDto commentToCommentDto(Comment entity);

  @Mappings({
      @Mapping(target = "content", source = "dto.content"),
      @Mapping(target = "user", source = "dto.user")
  })
  Comment commentDtoToComment(CommentDto dto);

}

我想知道是否有可能以某种方式在流温柔中使用此接口方法来映射我的值,而无需包装如下值:

public Optional<CommentDto> findCommentById(final long id) {

    Optional<Comment> commentById = commentRepository.findById(id);
    return Optional.ofNullable(commentMapper.commentToCommentDto(commentById.get()));
}

感谢您的帮助。

【问题讨论】:

  • 可选 = 一个容器对象,它可能包含也可能不包含非空值。如果没有注释,请不要将其作为“findById”方法的结果返回,只需返回 null!评论评论 = commentRepository.findById(id).orElse(null);
  • MapStructs 就像 lombok 一个经过预处理的接口,它正在生成一个 Impl 类。

标签: java stream dto mapstruct


【解决方案1】:

像这样访问映射器:

private static final YourMapper MAPPER = Mappers.getMapper(YourMapper.class);

final Optional<YourEntity> optEntity = entityRepo.findById(id);
return optEntity.map(MAPPER::toDto).orElse(null);

基本上我们用枚举做类似的事情

 @Mapping(target = "type", expression = "java(EnumerationType.valueOf(entity.getType()))")

您可以在 @Mapping 注解中定义 java 表达式

@Mapping(target = "comment", expression = "java(commentMapper.commentToCommentDto(commentRepository.findById(entity.commentId).orElse(null)))"

否则你应该能够使用一个

class CommentMapper { ... }

你可以自动参考

@Mapper(uses = {CommentMapper.class})

您的实现将检测commentEntity 和Dto,并自动使用CommentMapper。

MapStruct 映射器的工作方式如下:Shit in Shit out,因此请记住您的实体需要 commentEntity,这样 dto 才能拥有 commentDto。

编辑

第二个解决方案可以使用:

@BeforeMapping
default void beforeMappingToDTO(Entity source, @MappingTarget Dto target) {
    target.setComment(commentMapper.commentToCommentDto(commentRepository.findById(entity.commentId).orElse(null)));
}

【讨论】:

  • 5 分钟前我找到了解决方案。无论如何,非常感谢您的快速回复。
  • @Martin 您是否使用了上述答案?您能指出哪种解决方案吗?请将其标记为已回答。 @Spektakulatius,我更喜欢您的第二个解决方案,但我想您需要将第二个解决方案中的commentRepository 传递为@Context。以github.com/mapstruct/mapstruct-examples/blob/master/…为例
  • @Sjaak 是的,我使用了第一个。如果我们使用注释使用映射整个集合,则第二种解决方案会很棒。对于我的特殊问题,我使用了第一个,例如:return commentRepository.findById(id).map(CommentMapper.MAPPER::commentToCommentDto);
  • @Sjaak 回答添加的问题。感谢您的承诺。
  • 感谢第二个解决方案。我想为目标设置一个默认值,但找不到怎么做。 @BeforeMapping 完成了这项工作
【解决方案2】:

@Spektakulatius 的回答解决了一个问题。

为了达到一个目标,我做了几个步骤: 首先,我创建了一个映射器对象以在 java 流中使用它:

private CommentMapper commentMapper = Mappers.getMapper(CommentMapper.class);

在最后一步中,我使用了我的对象 commentMapper,例如:

public Optional<CommentDto> findCommentById(final long id) {
    return commentRepository.findById(id).map(CommentMapper.MAPPER::commentToCommentDto);
}

毕竟这完全让我有可能在流中使用我的自定义 MapStruct 映射器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 2014-03-13
    • 2012-03-17
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多