tsarenkotxt
tsarenkotxt

Reputation: 3489

mapstruct mapping Entity OneToMany to DTO and reverse

I'm trying to use a mapstruct and I need to mapping Entity with a sub Entity list, I have relationship oneToMany and manyToOne and I need to mapping in both cases:

@Data
@Entity
public class EmailEntity {

private int id;  

... // some fields

@ManyToOne
private DeliveredEmailInfoEntity deliveredEmailInfo;

}

.

@Data
@Entity
public class DeliveredEmailInfoEntity {

private int id;

... // some fields  

@OneToMany
private List<EmailEntity> emails;

}

mapping to:

@Data
public class EmailDTO {

private int id;  

... // some fields

private DeliveredEmailInfoDTO deliveredEmailInfo;

}

.

@Data
public class DeliveredEmailInfoDTO {

private int id;

... // some fields  

private List<EmailDTO> emails;

}

How to do it in the best way ?

Upvotes: 3

Views: 9256

Answers (2)

kolya_metallist
kolya_metallist

Reputation: 619

To avoid infinite cross setting of nested fields you should limit this dependency, for example on the second nested level, i.e. your root EmailDTO will have one nested DeliveredEmailInfoDTO object (many-to-one relationship), while your root DeliveredEmailInfoDTO will have the list of nested EmailDTO objects (one-to-many relationship) and nothing on the next nesting level:

@Mapper(uses = DeliveredEmailInfoMapper.class)
public interface EmailMapper {

    @Mapping(target = "deliveredEmailInfo.emails", ignore = true)
    EmailDTO toDTO(EmailEntity entity);

    // other methods omitted 

    @Named("emailDTOList")
    default List<EmailDTO> toEmailDTOList(List<EmailEntity> source) {
        return source
                .stream()
                .map(this::toDTO)
                .peek(dto -> dto.setDeliveredEmailInfo(null))
                .collect(Collectors.toList());
    }
}

@Mapper(uses = EmailMapper.class)
public interface DeliveredEmailInfoMapper {

    @Mapping(target = "emails", source = "emails", qualifiedByName = "emailDTOList")
    DeliveredEmailInfoDTO toDTO(DeliveredEmailInfoEntity entity);

    // other methods omitted 

}

Upvotes: 6

tkruse
tkruse

Reputation: 10685

(Also see other answer)

It should be straightforward, there is nothing challenging in your case:

@Mapper
public interface EmailInfoMapper {

    EmailDTO entityToDTO(EmailEntity duration);
    EmailEntity dtoToEntity(EmailDTO price);

    DeliveredEmailInfoDTO entityToDTO(DeliveredEmailInfoEntity duration);
    DeliveredEmailInfoEntity dtoToEntity(DeliveredEmailInfoDTO price);
}

You should include your mapper in your question and what the problem you have with it.

Upvotes: 0

Related Questions