MapStruct
1 MapStruct
- MapStruct는 type-safe하게 빈과 빈을 매핑시켜주는 annotation processor이다.
- 개발자는 mapper 인터페이스만 작성하면 컴파일 시점에 MapStruct가 해당 인터페이스의 구현을 자동으로 만들어준다.
- 소스 객체에서 타켓 객체로 매핑할 때 자바의 평범한 메소드를 이용해 매핑한다
- 리플렉션을 사용하지 않아 성능이 좋다.
2 Dependency
Maven
<properties>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Gradle
plugins {
id "com.diffplug.eclipse.apt" version "3.26.0" // Only for Eclipse
}
dependencies {
implementation "org.mapstruct:mapstruct:${mapstructVersion}"
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
// If you are using mapstruct in test code
testAnnotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
}
3 Defining a mapper
- mapper를 만들고 싶다면 인터페이스만 정의하고 인터페이스에
@Mapper애노테이션을 적용한다. - MapStruct가 빌드 시점의 인터페이스의 구현체를 만들어 준다.
3.1 Basic mappings
- 소스 엔티티와 타겟 엔티티의 프로퍼티 이름이 같으면 자동적으로 매핑
- 소스 엔티티와 타겟 엔티티의 프로퍼티 이름이 다르면
@Mapping애노테이션을 통해 명시
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface CarMapper {
@Mapping(source = "make", target = "manufacturer")
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
@Mapping(source = "name", target = "fullName")
PersonDto personToPersonDto(Person person);
}
Code generated by MapStruct
- 아래는 MapStruct가 생성한 CarMapper 인터페이스의 구현체다.
- 리플렉션 없이 게터와 세터를 이용해 빈과 빈을 매핑하고 있다.
public class CarMapperImpl implements CarMapper {
@Override
public CarDto carToCarDto(Car car) {
if ( car == null ) {
return null;
}
CarDto carDto = new CarDto();
if ( car.getFeatures() != null ) {
carDto.setFeatures( new ArrayList<String>( car.getFeatures() ) );
}
carDto.setManufacturer( car.getMake() );
carDto.setSeatCount( car.getNumberOfSeats() );
carDto.setDriver( personToPersonDto( car.getDriver() ) );
carDto.setPrice( String.valueOf( car.getPrice() ) );
if ( car.getCategory() != null ) {
carDto.setCategory( car.getCategory().toString() );
}
carDto.setEngine( engineToEngineDto( car.getEngine() ) );
return carDto;
}
@Override
public PersonDto personToPersonDto(Person person) {
//...
}
private EngineDto engineToEngineDto(Engine engine) {
if ( engine == null ) {
return null;
}
EngineDto engineDto = new EngineDto();
engineDto.setHorsePower(engine.getHorsePower());
engineDto.setFuel(engine.getFuel());
return engineDto;
}
}