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?