MapStruct
- Dto를 Entity로 매핑(반대도 가능)해주는 라이브러리다.
- 리플렉션이 아닌 직접 메소드를 호출하는 방식으로 동작하여 속도가 빠르다.
Set up
...
<properties>
<java.version>11</java.version>
<org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
<org.projectlombok.version>1.18.12</org.projectlombok.version>
</properties>
...
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration> <!-- java 버전을 따름-->
<source>11</source>
<target>11</target>
<annotationProcessorPaths> <!-- mapstruct 를 호출시 lombok 과 충돌 발생. 그래서 mapstruct와 lombok 에 대한 path 추가(mapstruct가 항상 lombok보다 우선 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs> <!-- 아래와 같이 의존성을 추가하면 매번 mapper에 @Mapper(componentModel = "spring")를 지정하지 안아도 된다. -->
<compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
...
주의!
lombok과 mapstruct을 같이 사용할 경우, path을 지정하지 않으면 충돌이 발생한다. annotationProcessorPaths 을 이용해 path을 지정한다.
<Entity>
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "price")
private int price;
@Enumerated(EnumType.STRING)
@Column(name = "color")
private Color color;
@Column(name = "name")
private String name;
}
<Dto>
@Getter
@Builder
public static class CarWebResponse{
private Long id;
private Color color;
private String name;
public static CarWebResponse of(Car car){
return CarMapper.INSTANCE.toCarWebResponse(car);
}
<Interface>
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
// Create
// - Entity -> WebDto
@Mapping(target = "id", source = "car.id")
CarWebDto.CarWebResponse toCarWebResponse(Car car);
}
- @Mapper 가 붙은 인터페이스는 MapStruct Code Generator가 해당 인터페이스의 구현체를 생성해준다.
- 구현체 생성 시 soruce가 되는 클래스와 target이 되는 클래스의 속성명을 비교하고 자동으로 매핑 코드를 작성한다.
- 매핑될 속성명이 다를 경우 @Mapping 어노테이션을 통해 매핑정보를 맞춰준다.
<Implementation>
Mapper을 생성했다면 아래와 같은 구현체를 자동으로 생성해준다.
package com.tmax.cicdpractice;
import com.tmax.cicdpractice.CarWebDto.CarWebResponse;
import com.tmax.cicdpractice.CarWebDto.CarWebResponse.CarWebResponseBuilder;
import javax.annotation.processing.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2022-05-04T10:09:33+0900",
comments = "version: 1.4.2.Final, compiler: javac, environment: Java 11.0.13 (Oracle Corporation)"
)
public class CarMapperImpl implements CarMapper {
@Override
public CarWebResponse toCarWebResponse(Car car) {
if ( car == null ) {
return null;
}
CarWebResponseBuilder carWebResponse = CarWebResponse.builder();
carWebResponse.id( car.getId() );
carWebResponse.color( car.getColor() );
carWebResponse.name( car.getName() );
return carWebResponse.build();
}
}
참고
https://ykh6242.tistory.com/entry/반복적인-DTO-변환-작업을-한-번에-정의-MapStruct-기본-정리
https://mapstruct.org/documentation/stable/reference/html/#setup
'Programming > Spring' 카테고리의 다른 글
ApplicationContext 2가지 빈 설정 방식 (0) | 2024.12.11 |
---|---|
RequestBody 자바 객체 매핑 (0) | 2024.12.11 |
@JsonProperty, @JsonNaming (0) | 2022.04.29 |
Entity, DTO, VO 차이 (0) | 2022.02.04 |
REST API (0) | 2022.01.25 |