Home » Java » java – How to map objects as fields with mapstruct?-Exceptionshub

java – How to map objects as fields with mapstruct?-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

I need to map multiples dto’s to entities.
Almost all of them have a reference to another one and I don’t know how to pass the reference while mapping the dto.

Here is one business implementation for the Address :

addressRepository.saveAll(dtos.stream()
                .map(addressMapper::asEntity)
                .collect(Collectors.toList())).stream()
                .map(addressMapper::asDto)
                .collect(Collectors.toList());

Here is the mapper

    @Mappings({
            @Mapping(target="streetName", source="streetName"),
            @Mapping(target="streetNumber", source="streetNumber"),
            @Mapping(target="block", source="block"),
            @Mapping(target="floor", source="floor")

    })
    CsvBusinessData asDto(AddressEntity address);

    @InheritInverseConfiguration
    AddressEntity asAddressEntity(CsvBusinessData address);

All the implementors reads from the same dto and then map them to dto and entites.

Here is for the customer implmentation :

customerRepository.saveAll(dtos.stream()
            .map( csvMapper::asCustomerEntity)

            .collect(Collectors.toList())).stream()
            .map(customerMapper::asDto)
            .collect(Collectors.toList()); 

And the mapping where I want a reference to mapped address entity (my customer entity has an Address type field).

 @Mappings({
            @Mapping(target = "nom", source = "lastName"),
            @Mapping(target = "nd", source = "accountNumber"),
            @Mapping(target = "logo", source = "logo"),
            @Mapping(target = "address", source = "address"
            )

    })
    CsvBusinessData asDto(CustomerEntity customer);

    @InheritInverseConfiguration
    CustomerEntity asCustomerEntity(CsvBusinessData customer);

Thank You very much.

How to&Answers:

First of all you don’t have to make mapping for fields with the same name, MapStruct doing it for you.For example block-block.
1)Your objects are related:
You could use “uses” funcrionality for related objects.

@Mapper(uses = {AddressMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CustomerMapper {
    @Mapping(target = "nom", source = "lastName")
    @Mapping(target = "nd", source = "accountNumber")
    @Mapping(target = "logo", source = "logo") //don't needed as same name, delete it
    @Mapping(target = "address", source = "address") //don't needed as same name, delete it
    CsvBusinessData asDto(CustomerEntity customer);

    @InheritInverseConfiguration
    CustomerEntity asCustomerEntity(CsvBusinessData customer);
}

@Mapper( unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CustomerMapper {
    @Mapping(target="streetName", source="streetName") //don't needed as same name, delete it
    @Mapping(target="streetNumber", source="streetNumber") //don't needed as same name, delete it
    @Mapping(target="block", source="block") //don't needed as same name, delete it
    @Mapping(target="floor", source="floor") //don't needed as same name, delete it
    CsvBusinessData asDto(AddressEntity address);
}

2)Your objects don’t related:
You could solve your case by passing few object as parameters. But then you must have your own methods for opposite direction. If you have same field name in AddressEntity and CustomerEntity then just specify it address.streetName or customer.lastName

@Mapping(target="streetName", source="streetName")//possibly don't needed as same name
@Mapping(target="streetNumber", source="streetNumber")//possibly don't needed as same name
@Mapping(target="block", source="block")//possibly don't needed as same name
@Mapping(target="floor", source="floor")//possibly don't needed as same name
@Mapping(target = "nom", source = "lastName")
@Mapping(target = "nd", source = "accountNumber")
@Mapping(target = "logo", source = "logo")//possibly don't needed as same name
@Mapping(target = "address", source = "customer.address") //specified as you have parameter address
CsvBusinessData asDto(AddressEntity address, CustomerEntity customer);

@Mapping(target="streetName", source="streetName")//possibly don't needed as same name
@Mapping(target="streetNumber", source="streetNumber")//possibly don't needed as same name
@Mapping(target="block", source="block")//possibly don't needed as same name
@Mapping(target="floor", source="floor")//possibly don't needed as same name
AddressEntity asAddressEntity(CsvBusinessData businessData);

@Mapping(source = "nom", target = "lastName")
@Mapping(source = "nd", target = "accountNumber")
@Mapping(source = "logo", target = "logo")//possibly don't needed as same name
@Mapping(source = "address", target = "address") //specified as you have parameter address
CustomerEntity asCustomerEntity(CsvBusinessData businessData);