1

I have a flat object (namely, an entity mapping a database View) that I want to map to a nested DTO.

public class VwPlanningAmlControl {
    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer controlid;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Year controlplanningyear;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Month controloccurrence;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private LocalDate controlexpirationdate;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private AmlControlStatusType controlstatus;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private OffsetDateTime controlconfirmed;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer controlconfirmedby;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private OffsetDateTime controlrejected;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer controlrejectedby;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private OffsetDateTime controlcreated;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer controlcreatedby;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private OffsetDateTime controlupdated;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer controlupdatedby;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String amltypetitle;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Short amltypeidelement;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer amltypeidversion;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer controlidversion;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Short controlelementid;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controltitle;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controldescription;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlcodeccb;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlperimeter;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlelementdescription;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlreferencekey;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private TaxonomyControlControlModeType controlcontrolmode;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlcontrollevel;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlapplicability;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlenhancement;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlnotcompliant;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlwithurgency;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlcompliant;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private TaxonomyControlSamplingType controlsampling;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlschedule;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private TaxonomyControlFrequencyType controlfrequency;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlperformer;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlowner;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controltarget;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlnotes;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private TaxonomyControlOutputType controloutput;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private TaxonomyControlFacilityType controlfacility;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlguidelines;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlinstructions;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String controlsignificance;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private TaxonomyControlSamplingModeType controlsamplingmode;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer confirmedbyid;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String confirmedbyfirstname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String confirmedbylastname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String confirmedbyemail;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer rejectedbyid;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String rejectedbyfirstname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String rejectedbylastname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String rejectedbyemail;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer createdbyid;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String createdbyfirstname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String createdbylastname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String createdbyemail;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private Integer updatedbyid;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String updatedbyfirstname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String updatedbylastname;

    @Generated("org.mybatis.generator.api.MyBatisGenerator")
    private String updatedbyemail;
}

Take ***id, ***firstName, ***lastName, ***email, where *** is a prefix from the User joined table (left joined, so columns can be null)

My target DTO and mapping follow

@Mapping(target = "id", source = "controlid")
    @Mapping(target = "amlType.id", source = "amltypeidelement")
    @Mapping(target = "amlType.description", source = "amltypetitle")
    @Mapping(target = "taxonomyId", source = "controlelementid")
    @Mapping(target = "planningYear", source = "controlplanningyear")
    @Mapping(target = "occurrence", source = "controloccurrence")
    @Mapping(target = "confirmed", source = "controlconfirmed")
    @Mapping(target = "confirmedBy.id", source = "confirmedbyid")
    @Mapping(target = "confirmedBy.firstName", source = "confirmedbyfirstname")
    @Mapping(target = "confirmedBy.lastName", source = "confirmedbylastname")
    @Mapping(target = "rejected", source = "controlrejected")
    @Mapping(target = "rejectedBy.id", source = "rejectedbyid")
    @Mapping(target = "rejectedBy.firstName", source = "rejectedbyfirstname")
    @Mapping(target = "rejectedBy.lastName", source = "rejectedbylastname")
    @Mapping(target = "controlId", source = "controlcodeccb")
    @Mapping(target = "title", source = "controltitle")
    @Mapping(target = "controlLevel", source = "controlcontrollevel")
    @Mapping(target = "perimeter", source = "controlperimeter")
    @Mapping(target = "expirationDate", source = "controlexpirationdate")
    @Mapping(target = "created", source = "controlcreated")
    @Mapping(target = "createdBy.id", source = "createdbyid")
    @Mapping(target = "createdBy.firstName", source = "createdbyfirstname")
    @Mapping(target = "createdBy.lastName", source = "createdbylastname")
    @Mapping(target = "modified", source = "controlupdated")
    @Mapping(target = "modifiedBy.id", source = "updatedbyid")
    @Mapping(target = "modifiedBy.firstName", source = "updatedbyfirstname")
    @Mapping(target = "modifiedBy.lastName", source = "updatedbylastname")
    PlanningAmlControlDTO toDto(VwPlanningAmlControl planningAmlControl);

public class UserPlanningDTO {

    private Integer id;

    private String  firstName;

    private String  lastName;

}

public class PlanningAmlControlDTO extends EventAmlControlDTO {

    private Integer id;

    private Integer planningYear;

    private Integer occurrence;

    private OffsetDateTime confirmed;

    private UserPlanningDTO confirmedBy;

    private OffsetDateTime rejected;

    private UserPlanningDTO rejectedBy;

    private OffsetDateTime expirationDate;

    private OffsetDateTime created;

    private UserPlanningDTO createdBy;

    private OffsetDateTime modified;

    private UserPlanningDTO modifiedBy;

}

Take as an example private UserPlanningDTO modifiedBy. Normally, either all source columns are null or not null.

But I just want that source columns are all null ==> return null

MapStructs returns an "empty" UserPlanningDTO.

Implementation generated by Mapstruct

@Override
    public PlanningAmlControlDTO toDto(VwPlanningAmlControl planningAmlControl) {
        if ( planningAmlControl == null ) {
            return null;
        }

        PlanningAmlControlDTO planningAmlControlDTO = new PlanningAmlControlDTO();

        planningAmlControlDTO.setAmlType( vwPlanningAmlControlToAmlTypeDTO( planningAmlControl ) );
        planningAmlControlDTO.setConfirmedBy( vwPlanningAmlControlToUserPlanningDTO( planningAmlControl ) );
        planningAmlControlDTO.setRejectedBy( vwPlanningAmlControlToUserPlanningDTO1( planningAmlControl ) );
        planningAmlControlDTO.setCreatedBy( vwPlanningAmlControlToUserPlanningDTO2( planningAmlControl ) );
        planningAmlControlDTO.setModifiedBy( vwPlanningAmlControlToUserPlanningDTO3( planningAmlControl ) );
        planningAmlControlDTO.setId( planningAmlControl.getControlid() );
        if ( planningAmlControl.getControlelementid() != null ) {
            planningAmlControlDTO.setTaxonomyId( planningAmlControl.getControlelementid().intValue() );
        }
        planningAmlControlDTO.setPlanningYear( fromYear( planningAmlControl.getControlplanningyear() ) );
        planningAmlControlDTO.setOccurrence( fromMonth( planningAmlControl.getControloccurrence() ) );
        planningAmlControlDTO.setConfirmed( planningAmlControl.getControlconfirmed() );
        planningAmlControlDTO.setRejected( planningAmlControl.getControlrejected() );
        planningAmlControlDTO.setControlId( planningAmlControl.getControlcodeccb() );
        planningAmlControlDTO.setTitle( planningAmlControl.getControltitle() );
        planningAmlControlDTO.setControlLevel( planningAmlControl.getControlcontrollevel() );
        planningAmlControlDTO.setPerimeter( planningAmlControl.getControlperimeter() );
        planningAmlControlDTO.setExpirationDate( map( planningAmlControl.getControlexpirationdate() ) );
        planningAmlControlDTO.setCreated( planningAmlControl.getControlcreated() );
        planningAmlControlDTO.setModified( planningAmlControl.getControlupdated() );

        return planningAmlControlDTO;
    }

protected UserPlanningDTO vwPlanningAmlControlToUserPlanningDTO(VwPlanningAmlControl vwPlanningAmlControl) {
        if ( vwPlanningAmlControl == null ) {
            return null;
        }

        UserPlanningDTO userPlanningDTO = new UserPlanningDTO();

        userPlanningDTO.setId( vwPlanningAmlControl.getConfirmedbyid() );
        userPlanningDTO.setFirstName( vwPlanningAmlControl.getConfirmedbyfirstname() );
        userPlanningDTO.setLastName( vwPlanningAmlControl.getConfirmedbylastname() );

        return userPlanningDTO;
    }

    protected UserPlanningDTO vwPlanningAmlControlToUserPlanningDTO1(VwPlanningAmlControl vwPlanningAmlControl) {
        if ( vwPlanningAmlControl == null ) {
            return null;
        }

        UserPlanningDTO userPlanningDTO = new UserPlanningDTO();

        userPlanningDTO.setId( vwPlanningAmlControl.getRejectedbyid() );
        userPlanningDTO.setFirstName( vwPlanningAmlControl.getRejectedbyfirstname() );
        userPlanningDTO.setLastName( vwPlanningAmlControl.getRejectedbylastname() );

        return userPlanningDTO;
    }

    protected UserPlanningDTO vwPlanningAmlControlToUserPlanningDTO2(VwPlanningAmlControl vwPlanningAmlControl) {
        if ( vwPlanningAmlControl == null ) {
            return null;
        }

        UserPlanningDTO userPlanningDTO = new UserPlanningDTO();

        userPlanningDTO.setId( vwPlanningAmlControl.getCreatedbyid() );
        userPlanningDTO.setFirstName( vwPlanningAmlControl.getCreatedbyfirstname() );
        userPlanningDTO.setLastName( vwPlanningAmlControl.getCreatedbylastname() );

        return userPlanningDTO;
    }

    protected UserPlanningDTO vwPlanningAmlControlToUserPlanningDTO3(VwPlanningAmlControl vwPlanningAmlControl) {
        if ( vwPlanningAmlControl == null ) {
            return null;
        }

        UserPlanningDTO userPlanningDTO = new UserPlanningDTO();

        userPlanningDTO.setId( vwPlanningAmlControl.getUpdatedbyid() );
        userPlanningDTO.setFirstName( vwPlanningAmlControl.getUpdatedbyfirstname() );
        userPlanningDTO.setLastName( vwPlanningAmlControl.getUpdatedbylastname() );

        return userPlanningDTO;
    }

Question

How can I tell Mapstruct to return null if all of the source properties taken into consideration are null?

usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305

0 Answers0