Mapstruct:如何将DTO中的多个字段映射到实体中的对象?

时间:2017-12-25 17:15:32

标签: mapstruct

我有这个DTO:

@NoArgsConstructor
public class DataDTO implements DTO {

    private static final long serialVersionUID = -5105904799152965475L;

    private Long deviceId;

    private OffsetDateTime generatedOn;

    public Long getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(Long deviceId) {
        this.deviceId = deviceId;
    }

    public OffsetDateTime getGeneratedOn() {
        return generatedOn;
    }

    public void setGeneratedOn(OffsetDateTime generatedOn) {
        this.generatedOn = generatedOn;
    }
}

我有这个MongoDB文档:

@Document(collection = "data")
@EqualsAndHashCode
public class DataDocument {

    private static final long serialVersionUID = 1772572723546311500L;

    @Id
    private IdByDeviceIdAndGeneratedOn id;

    public DataDocument() {
    }

    public IdByDeviceIdAndGeneratedOn getId() {
        return id;
    }

    public void setId(IdByDeviceIdAndGeneratedOn id) {
        this.id = id;
    }
}

这是MongoDB文档的@Id类:

@EqualsAndHashCode
@ToString
public class IdByDeviceIdAndGeneratedOn {

    @Id
    private final Long deviceId;

    @Id
    @Field("generated_on")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private final OffsetDateTime generatedOn;

    public IdByDeviceIdAndGeneratedOn(final Long deviceId, final OffsetDateTime         generatedOn) {
        this.deviceId = Objects.requireNonNull(deviceId);
        this.generatedOn = Objects.requireNonNull(generatedOn);
    }

    public Long getDeviceId() {
        return deviceId;
    }

    public OffsetDateTime getGeneratedOn() {
        return generatedOn;
    }
}

这是此Key类的映射器:

@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, componentModel = "spring")
public interface IdByDeviceIdAndGeneratedOnMapper {

    default IdByDeviceIdAndGeneratedOn toId(final Long deviceId, final   OffsetDateTime generatedOn) {
        return new IdByDeviceIdAndGeneratedOn(deviceId, generatedOn);
    }
    default Long getDeviceId(final IdByDeviceIdAndGeneratedOn id) {
        return id.getDeviceId();
    }

    default OffsetDateTime getGeneratedOn(final IdByDeviceIdAndGeneratedOn id) {
        return id.getGeneratedOn();
    }

这是DataDTO和DataDocument的@Mapper:

@Mapper( unmappedTargetPolicy = ReportingPolicy.ERROR,
    uses = {IdByDeviceIdAndGeneratedOnMapper.class,
            AccelerometerDocumentMapper.class,
            GpsDocumentMapper.class,
            GsmDocumentMapper.class
})
public interface DataDocumentMapper extends DocumentMapper<DataDTO, DataDocument> {

}

这是通用映射器:

/**
 * Contract for a generic dto to entity mapper.
 *
 * @param <DTO> - DTO source type parameter.
 * @param <DOCUMENT> - MongoDB Document destination type parameter.
 */

public interface DocumentMapper<DTO, DOCUMENT> {

DOCUMENT toDocument(DTO dto);

DTO toDto(DOCUMENT document);

}

目前我收到此错误: 对于MongoDB数据文档:

  

未映射的目标属性:“id”。

DTO的

  

未映射的目标属性:“deviceId,generatedOn”。

如何在不失去Id类不变性的情况下解决这些错误?

2 个答案:

答案 0 :(得分:0)

这解决了我的问题,但这看起来并不优雅。 也许有更优雅的方式?

@Mapper(uses = {AccelerometerDocumentMapper.class,
            GpsDocumentMapper.class,
            GsmDocumentMapper.class},
imports = {IdByDeviceIdAndGeneratedOn.class},
componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface DataDocumentMapper extends DocumentMapper<DataDTO, DataDocument> {

@Override
@Mapping(target = "id", expression = "java( new IdByDeviceIdAndGeneratedOn(dto.getDeviceId(), dto.getGeneratedOn()) )")
DataDocument toDocument(DataDTO dto);

@Override
@Mapping(target = "deviceId",    expression = "java( document.getId().getDeviceId() )")
@Mapping(target = "generatedOn", expression = "java( document.getId().getGeneratedOn() )")
DataDTO toDto(DataDocument document);
}

答案 1 :(得分:0)

您要做的是使用(使用构造函数构造对象)尚不支持。它有一个未解决的问题#73

但是,您可以使用Object factories实现所需内容,这适用于toDocument映射,toDto映射可以使用嵌套源映射。

您的映射器看起来像:

@Mapper(uses = {AccelerometerDocumentMapper.class,
            GpsDocumentMapper.class,
            GsmDocumentMapper.class},
componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface DataDocumentMapper extends DocumentMapper<DataDTO, DataDocument> {

    @Mapping(target = "id", source = "dto")
    @Override
    DataDocument toDocument(DataDTO dto);

    @ObjectFactory
    default IdByDeviceIdAndGeneratedOn createId(DataDTO dto) {
        return dto == null ? null : new IdByDeviceIdAndGeneratedOn(dto.getDeviceId(), dto.getGeneratedOn());
    }


    @Mapping(target = "deviceId", source = "id.deviceId")
    @Mapping(target = "generatedOn", source = "id.generatedOn")
    @Override
    DataDTO toDto(DataDocument document);
}

注意:您还可以制作DataDocumentMapper抽象类并使createId方法受到保护,以防您不想在界面中公开它