Motivation
Context
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private String firstName;
@NotNull
private String lastName;
@NotNull
private Integer dayOfBirth;
@NotNull
private Integer monthOfBirth;
@NotNull
private Integer yearOfBirth;
private String address;
private Integer houseNumber;
private String houseNumberAddition;
private String city;
private String country;
// getters and setters
.....
}
public class Customer2DTO {
private Long id;
private String name;
private String familyName;
private String fullName;
private LocalDate birthDay;
private String address;
private Integer houseNumber;
private String houseNumberAddition;
private String city;
private String country;
// getters and setters
....
}
Adding MapStruct to our project
First usage of MapStruct
import org.mapstruct.Mapper;
@Mapper
public interface Customer2Mapper {
}
Customer2Mapper INSTANCE = Mappers.getMapper(Customer2Mapper.class);
Customer2DTO customerToCustomerDTO(Customer customer);
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.dto.Customer2DTO;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.pojo.Customer;
@Mapper
public interface Customer2Mapper {
Customer2Mapper INSTANCE = Mappers.getMapper(Customer2Mapper.class);
Customer2DTO customerToCustomerDTO(Customer customer);
}
Customer2DTO c2dto = Customer2Mapper.INSTANCE.customerToCustomerDTO(customer);
Renaming fields
@Mapping(source = "firstName", target = "name")
@Mapping(source = "lastName", target = "familyName")
Combining multiple fields
@Mapping(target="fullName", expression = "java(customer.getFirstName() +\" \"+ customer.getLastName())")
@Mapping(target="birthDay", expression = "java(java.time.LocalDate.of(customer.getYearOfBirth(), customer.getMonthOfBirth(), customer.getDayOfBirth()))")
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.dto.Customer2DTO;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.pojo.Customer;
@Mapper
public interface Customer2Mapper {
Customer2Mapper INSTANCE = Mappers.getMapper(Customer2Mapper.class);
@Mapping(source = "firstName", target = "name")
@Mapping(source = "lastName", target = "familyName")
@Mapping(target="fullName", expression = "java(customer.getFirstName() +\" \"+ customer.getLastName())")
@Mapping(target="birthDay", expression = "java(java.time.LocalDate.of(customer.getYearOfBirth(), customer.getMonthOfBirth(), customer.getDayOfBirth()))")
Customer2DTO customerToCustomerDTO(Customer customer);
}
Creating “sub-objects” inside Data Transfer objects
public class HomeAddressDTO {
private String street;
private Integer houseNumber;
private String addition;
private String city;
private String country;
//getters and setters
....
}
public class Customer3DTO {
private Long id;
private String name;
private String familyName;
private String fullName;
private LocalDate birthDay;
private HomeAddressDTO homeAddress;
// getters and setters
....
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.dto.Customer3DTO;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.pojo.Customer;
@Mapper
public interface Customer3Mapper {
Customer3Mapper INSTANCE = Mappers.getMapper(Customer3Mapper.class);
@Mapping(source = "firstName", target = "name")
@Mapping(source = "lastName", target = "familyName")
@Mapping(target="fullName", expression = "java(customer.getFirstName() +\" \"+ customer.getLastName())")
@Mapping(target="birthDay", expression = "java(java.time.LocalDate.of(customer.getYearOfBirth(), customer.getMonthOfBirth(), customer.getDayOfBirth()))")
@Mapping(target="homeAddress.street",source="address")
@Mapping(target="homeAddress.houseNumber",source="houseNumber")
@Mapping(target="homeAddress.addition",source="houseNumberAddition")
@Mapping(target="homeAddress.city",source="city")
@Mapping(target="homeAddress.country",source = "country")
Customer3DTO customerToCustomerDTO(Customer customer);
}
public class DummyCustomerBuilder {
public static Customer dummyCustomer() {
Customer customer = new Customer();
customer.setId((long)1);
customer.setFirstName("Sherlock");
customer.setLastName("Holmes");
customer.setCity("London");
customer.setCountry("Great Britan");
customer.setHouseNumber(221);
customer.setHouseNumberAddition("B");
customer.setAddress("Baker Street");
customer.setDayOfBirth(6);
customer.setMonthOfBirth(1);
customer.setYearOfBirth(1854);
return customer;
}
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.dto.Customer3DTO;
import xyz.itshark.blog.mapstructdemo.mapstructdemo.pojo.Customer;
import java.time.LocalDate;
public class Customer3MapperTest {
// .........
@Test
public void testMappingHomeAddress() {
//given
Customer customer = DummyCustomerBuilder.dummyCustomer();
//when
Customer3DTO cDto = Customer3Mapper.INSTANCE.customerToCustomerDTO(customer);
//then
Assertions.assertNotNull(cDto);
Assertions.assertNotNull(cDto.getHomeAddress());
Assertions.assertEquals("Baker Street",cDto.getHomeAddress().getStreet());
Assertions.assertEquals(Integer.valueOf(221), cDto.getHomeAddress().getHouseNumber());
Assertions.assertEquals("B",cDto.getHomeAddress().getAddition());
Assertions.assertEquals("London", cDto.getHomeAddress().getCity());
Assertions.assertEquals("Great Britan",cDto.getHomeAddress().getCountry());
}
}
Conclusion
## Resources
Author: Vladimir Dejanovic
Founder and leader of AmsterdamJUG.
JavaOne Rock Star, CodeOne Star speaker
Storyteller
Software Architect ,Team Lead and IT Consultant working in industry since 2006 developing high performance software in multiple programming languages and technologies from desktop to mobile and web with high load traffic.
Enjoining developing software mostly in Java and JavaScript, however also wrote fair share of code in Scala, C++, C, PHP, Go, Objective-C, Python, R, Lisp and many others.
Always interested in cool new stuff, Free and Open Source software.
Like giving talks at conferences like JavaOne, Devoxx BE, Devoxx US, Devoxx PL, Devoxx MA, Java Day Istanbul, Java Day Minks, Voxxed Days Bristol, Voxxed Days Bucharest, Voxxed Days Belgrade, Voxxed Days Cluj-Napoca and others
steinhauer.software