Overview
MapStruct is a library that helps in converting DTOs and Entities.
- Automatically generates the implementation for a mapper interface at compile time, giving you fast, type-safe, and boilerplate-free code for your conversions.
- If you use this well, your working time will decrease tremendously!
Initialization
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// add these
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}Example
Product - The Entity
@Data
@Entity
@Getter
public class Product {
@Id
private Long id;
private String name; // <<<
private String description;
private double price;
}ProductDto - The Dto
@Data
public class ProductDto {
private Long id;
private String productName; // << Different name from the entity
private String description;
private double price;
}The Mapper
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper(componentModel = "spring")
public interface ProductMapper {
// You can define an instance for non-Spring usage if needed
// ProductMapper INSTANCE = Mappers.getMapper(ProductMapper.class);
/**
* Maps a Product Entity to a Product DTO.
* The field 'name' in Product is mapped to 'productName' in ProductDto.
* Fields 'id', 'description', and 'price' are mapped automatically by name.
*/
@Mapping(source = "name", target = "productName")
ProductDto toDto(Product product);
/**
* Maps a Product DTO back to a Product Entity.
* The field 'productName' in the DTO is mapped back to 'name' in the Entity.
*/
@Mapping(source = "productName", target = "name")
Product toEntity(ProductDto productDto);
}@Mapper(componentModel = "spring")- tells MapStruct to generate an implementation that is a Spring bean
- You have to put this on top of every mapper
source,target- source = from
- target = to
NOT a proxy
-
Mapstruct is an annotation processor that runs during your project’s compile time (ex. when you build your project using gradle or maven)
-
What happens
- It scans your code with interfaces with
@Mapper, reads the method signatures and@Mappingannotations inside that interface - It then generates a concrete Java implementation class for that interface! ⇒ Ex.
ProductMapperImpl.java - This generated class is plain java that performs the getter & setter calls, and is also compiled into bytecode along with the rest of the code
- It scans your code with interfaces with
-
MapStruct vs ModelMapper
- ModelMapper - 리플렉션을 써서 동적으로 가지고 와서 매핑해줌.
- MapStruct - 훨씬 빠름. 클래스파일 만듬 → 빌드 → build folder에 classes/member/mapper/mapstruct → 구현 클래스가 만들어져있음!!!
- 빌드되는 시점에 구현 클래스를 만들어줌
- 클래스: 기본생성자 + setter / 전체생성자 / 빌더 << 다 대응을함
- 클래스에 다 있으면, mapper은 뭘 쓸지 헷갈려함
- 빌더 > 전체생성자 > 기본생성자
- 아무것도 없으면 안만들어짐
- 클래스에 다 있으면, mapper은 뭘 쓸지 헷갈려함
-
proxy아님!
default 쓰는 것 대신 바로 알려주는 것
- annotation 사용