I am new to MapStruct and so I might be doing something very stupid. Apologies in advance. I use Spring Boot 1.5.3 and JHipster for generating the code using JDL. MapStruct is used for mapping Entity to DTO and vice-versa.
I have an object Currency, which holds the primary information of a currency such as currency code, currency symbol etc. CurrencyTl class holds the descriptive information of currency such as name, description etc in various languages supported by the application. Languages hold the definition of languages supported by the application.
Currency
public class Currency extends AbstractEffectiveEntity {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name = "id", columnDefinition = "CHAR", length = 36, nullable = false)
private String id;
@Column(name = "currency_code", columnDefinition = "CHAR", length = 5, nullable = false, updatable = false)
private String currencyCode;
@Column(name = "currency_symbol", columnDefinition = "VARCHAR", length = 10, nullable = false, updatable = false)
private String currencySymbol;
@Column(name = "installed_flag", columnDefinition = "CHAR", length = 1, nullable = false)
private String installedFlag;
@OneToMany(mappedBy = "currency")
@JsonIgnore
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<CurrencyTl> currencyTls = new HashSet<>();
// Getters and Setters (Avoided for brevity)
}
CurrencyTl
public class CountryTl extends AbstractEntity {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(columnDefinition = "CHAR", length = 36, nullable = false)
private String id;
@Column(name = "entity_name", columnDefinition = "VARCHAR", length = 120, nullable = false)
private String entityName;
@Column(name = "entity_desc", columnDefinition = "VARCHAR", length = 256, nullable = true)
private String entityDesc;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "country_id", nullable = false)
private Country country;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "language_id", nullable = false)
private Language language;
// Getters and Setters
}
Language
public class Language extends AbstractEffectiveEntity {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name = "id", columnDefinition = "CHAR", length = 36, nullable = false)
private String id;
@Column(name = "language_code", columnDefinition = "CHAR", length = 5, nullable = false)
private String languageCode;
@Column(name = "language_name", columnDefinition = "VARCHAR", length = 80, nullable = false)
private String languageName;
// Getters and Setters
}
Mapper Interface
public interface EntityMapper<D, E> {
E toEntity(D dto);
D toDto(E entity);
List<E> toEntity(List<D> dtoList);
List<D> toDto(List<E> entityList);
}
I created Mapper interface for Country, Language and CountryTl by extending the above interface. CountryTlMapper interface is defined as follows:
CountryTlMapper
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.WARN, uses = {LanguageMapper.class, CurrencyMapper.class})
public interface CurrencyTlMapper extends EntityMapper<CurrencyTlDTO, CurrencyTl> {
@Mapping(source = "language.id", target = "languageId")
@Mapping(source = "currency.id", target = "currencyId")
@Override
CurrencyTlDTO toDto(CurrencyTl currencyTl);
@Mapping(source = "languageId", target = "language")
@Mapping(source = "currencyId", target = "currency")
@Override
CurrencyTl toEntity(CurrencyTlDTO currencyTlDTO);
default CurrencyTl fromId(String id) {
if (id == null) {
return null;
}
CurrencyTl currencyTl = new CurrencyTl();
currencyTl.setId(id);
return currencyTl;
}
}
The above results in MapStruct generating the implementation class as follows:
CurrencyTlMapperImpl
@Component
public class CurrencyTlMapperImpl implements CurrencyTlMapper {
@Autowired
private LanguageMapper languageMapper;
@Autowired
private CurrencyMapper currencyMapper;
@Override
public List<CurrencyTl> toEntity(List<CurrencyTlDTO> dtoList) {
// Removed for brevity
return list;
}
@Override
public List<CurrencyTlDTO> toDto(List<CurrencyTl> entityList) {
// Removed for brevity
return list;
}
@Override
public CurrencyTlDTO toDto(CurrencyTl currencyTl) {
if ( currencyTl == null ) {
return null;
}
CurrencyTlDTO currencyTlDTO = new CurrencyTlDTO();
String id = currencyTlLanguageId( currencyTl );
if ( id != null ) {
currencyTlDTO.setLanguageId( Long.parseLong( id ) );
}
String id1 = currencyTlCurrencyId( currencyTl );
if ( id1 != null ) {
currencyTlDTO.setCurrencyId( Long.parseLong( id1 ) );
}
currencyTlDTO.setId( currencyTl.getId() );
currencyTlDTO.setEntityName( currencyTl.getEntityName() );
currencyTlDTO.setEntityDesc( currencyTl.getEntityDesc() );
return currencyTlDTO;
}
@Override
public CurrencyTl toEntity(CurrencyTlDTO currencyTlDTO) {
if ( currencyTlDTO == null ) {
return null;
}
CurrencyTl currencyTl = new CurrencyTl();
if ( currencyTlDTO.getLanguageId() != null ) {
currencyTl.setLanguage( languageMapper.fromId( String.valueOf( currencyTlDTO.getLanguageId() ) ) );
}
if ( currencyTlDTO.getCurrencyId() != null ) {
currencyTl.setCurrency( currencyMapper.fromId( String.valueOf( currencyTlDTO.getCurrencyId() ) ) );
}
currencyTl.setId( currencyTlDTO.getId() );
currencyTl.setEntityName( currencyTlDTO.getEntityName() );
currencyTl.setEntityDesc( currencyTlDTO.getEntityDesc() );
return currencyTl;
}
private String currencyTlLanguageId(CurrencyTl currencyTl) {
if ( currencyTl == null ) {
return null;
}
Language language = currencyTl.getLanguage();
if ( language == null ) {
return null;
}
String id = language.getId();
if ( id == null ) {
return null;
}
return id;
}
private String currencyTlCurrencyId(CurrencyTl currencyTl) {
if ( currencyTl == null ) {
return null;
}
Currency currency = currencyTl.getCurrency();
if ( currency == null ) {
return null;
}
String id = currency.getId();
if ( id == null ) {
return null;
}
return id;
}
}
CurrencyDTO
public class CurrencyDTO extends AbstractEffectiveEntityDTO implements Serializable {
private static final long serialVersionUID = -3989102119178748641L;
@Size(max = 36)
private String id;
@NotNull
@Size(min = 2, max = 5)
private String currencyCode;
@NotNull
@Size(min = 2, max = 10)
private String currencySymbol;
@NotNull
@Size(max = 1)
private String installedFlag;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCurrencyCode() {
return currencyCode;
}
public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}
public String getCurrencySymbol() {
return currencySymbol;
}
public void setCurrencySymbol(String currencySymbol) {
this.currencySymbol = currencySymbol;
}
public String getInstalledFlag() {
return installedFlag;
}
public void setInstalledFlag(String installedFlag) {
this.installedFlag = installedFlag;
}
}
CurrencyTlDTO
public class CurrencyTlDTO implements Serializable {
private static final long serialVersionUID = 1142708918251175249L;
@Size(max = 36)
private String id;
@NotNull
@Size(max = 120)
private String entityName;
@Size(max = 256)
private String entityDesc;
private Long languageId;
private Long currencyId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEntityName() {
return entityName;
}
public void setEntityName(String entityName) {
this.entityName = entityName;
}
public String getEntityDesc() {
return entityDesc;
}
public void setEntityDesc(String entityDesc) {
this.entityDesc = entityDesc;
}
public Long getLanguageId() {
return languageId;
}
public void setLanguageId(Long languageId) {
this.languageId = languageId;
}
public Long getCurrencyId() {
return currencyId;
}
public void setCurrencyId(Long currencyId) {
this.currencyId = currencyId;
}
}
LanguageDTO
public class LanguageDTO extends AbstractEffectiveEntityDTO implements Serializable {
private static final long serialVersionUID = 8419729079888691835L;
private String id;
@NotNull
@Size(min = 2, max = 5)
private String languageCode;
@NotNull
@Size(min = 5, max = 80)
private String languageName;
@NotNull
@Size(min = 3, max = 80)
private String languageNativeName;
@Size(max = 256)
private String languageIcon;
@NotNull
@Size(max = 1)
private String installedFlag;
@NotNull
@Size(max = 1)
private String defaultFlag;
public LanguageDTO() {
// Emply constructor need for Jaskson
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLanguageCode() {
return languageCode;
}
public void setLanguageCode(String languageCode) {
this.languageCode = languageCode;
}
public String getLanguageName() {
return languageName;
}
public void setLanguageName(String languageName) {
this.languageName = languageName;
}
public String getLanguageNativeName() {
return languageNativeName;
}
public void setLanguageNativeName(String languageNativeName) {
this.languageNativeName = languageNativeName;
}
public String getLanguageIcon() {
return languageIcon;
}
public void setLanguageIcon(String languageIcon) {
this.languageIcon = languageIcon;
}
public String getInstalledFlag() {
return installedFlag;
}
public void setInstalledFlag(String installedFlag) {
this.installedFlag = installedFlag;
}
public String getDefaultFlag() {
return defaultFlag;
}
public void setDefaultFlag(String defaultFlag) {
this.defaultFlag = defaultFlag;
}
}
I am not sure what made MapStruct to treat the id of language and currency as Long !! This line fails currencyTlDTO.setCurrencyId( Long.parseLong( id1 ) ) since all id attributes are string and stores UUID value in the form 1edd1914-783d-11e8-9e18-9801a7b6295b. Can someone please suggest me where I am wrong and how the above can be fixed where MapStruct takes the datatype of an attribute as is defined? Thanks in advance.