user1134181 :
I need to convert some entity and list of entities to a single DTO by using MapStruct. This DTO includes nested list.
Let's say, I have the following persistence-backed POJO:
public class Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name", nullable = false)
private String name;
// SKIPPED
@OneToOne(mappedBy = "entity", cascade = CascadeType.ALL)
private EntityMetadata entityMetadata;
}
And some collection of this entities:
List<Entity> entities
DTO is presented below:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ScreenDocumentDto { // dto
private Long id;
private String name;
List<SomeLinkDto> someLinks;
}
And nested DTO:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SomeLinkDto {
private Long id;
private ZonedDateTime someDate;
}
All the fields except the someLinks list I need to map from entity:
dto.setId(entity.getId());
dto.setName(entity.getName());
// SKIPPED
Nested list I populate as follows:
List<SomeLinkDto> someLinks = new ArrayList<>(entities.size());
for (Entity entity : entities) {
someLinks.add(SomeLinkDto.builder().id(entity.getId())
.someDate(entity.getEntityMetadata().getSomeDate()).build());
}
The result involves a lot of manually transformations:
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
default ScreenDocumentDto toScreenDocumentDto(List<Entity> entities, Entity entity) {
ScreenDocumentDto dto = new ScreenDocumentDto();
List<SomeLinkDto> someLinks = new ArrayList<>(entities.size());
for (Entity entity : entities) {
someLinks.add(SomeLinkDto.builder().id(entity.getId())
.someDate(entity.getEntityMetadata().getSomeDate()).build());
}
dto.setId(entity.getId());
dto.setName(entity.getName());
...
dto.setSomeLinks(someLinks);
return dto;
}
// SKIPPED
Is there a way to do the same job by using features of MapStruct? Like that:
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
@Mappings({
@Mapping(source = "...", target = "..."),
...
})
ScreenDocumentDto toDto(Entity entity);
}
Filip :
You can achieve the custom toScreenDocumentDto
method with MapStruct by using multiple source parameters.
For example
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
@Mapping(source = "entities", target = "someLinks")
ScreenDocumentDto toDto(Entity entity, List<Entity> entities);
@Mapping(source = "entityMetadata.someDate", target = "someDate")
SomeLinkDto toLinkDto(Entity entity);
}
In case the Entity
has the links as a property you can do:
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
@Mapping(source = "links", target = "someLinks")
ScreenDocumentDto toDto(Entity entity);
@Mapping(source = "entityMetadata.someDate", target = "someDate")
SomeLinkDto toLinkDto(Entity entity);
}