Reputation: 658
i have this 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;
}
}
i have this MongoDB document:
@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;
}
}
and this is the @Id class for MongoDB Document:
@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;
}
}
this is the mapper for this Key class:
@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();
}
and this is the @Mapper for DataDTO and DataDocument:
@Mapper( unmappedTargetPolicy = ReportingPolicy.ERROR,
uses = {IdByDeviceIdAndGeneratedOnMapper.class,
AccelerometerDocumentMapper.class,
GpsDocumentMapper.class,
GsmDocumentMapper.class
})
public interface DataDocumentMapper extends DocumentMapper<DataDTO, DataDocument> {
}
this is the generic mapper:
/**
* 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);
}
Currently i'm receiving this errors: for MongoDB Data docment:
Unmapped target property: "id".
for DTO:
Unmapped target properties: "deviceId, generatedOn".
How to solve this errors without loosing immutability of Id class?
Upvotes: 1
Views: 6745
Reputation: 21393
What you are trying to do is to use (using constructors to construct objects) is not yet supported. There is an open issue for it #73.
However, you can achieve what you are looking for by using Object factories, this is for the toDocument
mapping, for the toDto
mapping you can use nested source mappings.
Your mapper would look like:
@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);
}
NB: You can also make DataDocumentMapper
abstract class and make the createId
method protected, in case you don't want to expose it in the interface
Upvotes: 3
Reputation: 658
this is solved my problem, but this doesnt look elegant. Maybe there is more elegant way?
@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);
}
Upvotes: 0