[Spring] MapStruct - Entity와 DTO 매핑하기
MapStruct
- Mapstruct란?
- Dependency 설정
- 사용법
- Entity, Dto 클래스를 만들어보자.
- Mapper를 만들자.
- 빌드를 진행하자.
MapStruct란?
MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach.
MapStruct는 구성접근법에 대한 규약에 근거하여 Java Bean 종류 간의 매핑 구현을 크게 단순화한 code generator이다.
참고 아래는 Java Mapping 프레임 워크 성능을 비교한 글이다.
https://www.baeldung.com/java-performance-mapping-frameworks
참고 아래는 ModelMapper 라이브러리에 대해 정리한 글이다.
https://frogand.tistory.com/180
* MapStruct는 시간당 처리량이 높다.
Dependency 설정 (의존성 설정)
참고 MapStruct 가이드
https://mapstruct.org/documentation/spring-extensions/reference/html/
1. maven 설정
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.2.Final</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.2.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
2. gradle 설정
dependencies {
implementation 'org.mapstruct:mapstruct:1.5.2.Final'
annotationProcessor "org.mapstruct:mapstruct-processor:1.5.2.Final"
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
}
사용법
1. 예시를 위한 Entity와 Dto 클래스를 만들어보자.
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import java.time.LocalDateTime;
@AllArgsConstructor
@Getter
@Builder
@EqualsAndHashCode
public class Order {
private Long id;
private String name;
private String product;
private Integer price;
private String address;
private LocalDateTime orderedTime;
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@Builder
class OrderDto {
private String name;
private String product;
private Integer price;
private String address;
private String img;
private LocalDateTime orderedTime;
}
* OrderDto 클래스에는 Long id 필드가 존재하지 않고, String img 필드가 만들어졌다.
* 변환해서 저장하고자 하는 객체에는 Builder 혹은 모든 필드를 담을 수 있는 생성자가 있어야 한다.
2. 이를 매핑하는 OrderMapper를 만들어보자.
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper // (1)
public interface OrderMapper {
OrderMapper INSTANCE = Mappers.getMapper(OrderMapper.class); // (2)
@Mapping(target = "id", constant = "0L") // (3)
Order convertOrderDtoToEntity(OrderDto orderDto);
@Mapping(target = "img", expression = "java(order.getProduct() + \".jpg\")") // (4)
OrderDto convertOrderToDto(Order order);
}
(1) @Mapper 어노테이션이 있어야 Mapstruct를 사용할 수 있다.
(2) 해당하는 Instance가 OrderMapper를 상속받아서 orderMapperImpl를 구현하게 될 것이다.
(3) 일반적인 경우에 @Mapping 어노테이션을 붙이면 된다. Order 에는 id 필드가 존재하기 때문에 id 필드를 0L로 지정하겠다는 의미이다. (ignore 파라미터를 사용하면 0L로 지정하는 것이 아니라 해당 필드를 무시할 수 있다.)
(4) OrderDto에는 img 필드가 존재하기 때문에 expression을 기반으로 img 필드를 지정할 수 있다.
3. 빌드 진행 후, MapperImpl 클래스가 생성된다.
import java.time.LocalDateTime;
import javax.annotation.processing.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2022-11-04T15:46:35+0900",
comments = "version: 1.5.2.Final, compiler: javac, environment: Java 1.8.0_311 (Oracle Corporation)"
)
public class OrderMapperImpl implements OrderMapper {
@Override
public Order orderDtoToEntity(OrderDto orderDto) {
if ( orderDto == null ) {
return null;
}
String name = null;
String product = null;
Integer price = null;
String address = null;
LocalDateTime orderedTime = null;
name = orderDto.getName();
product = orderDto.getProduct();
price = orderDto.getPrice();
address = orderDto.getAddress();
orderedTime = orderDto.getOrderedTime();
Long id = (long) 0L;
Order order = new Order( id, name, product, price, address, orderedTime );
return order;
}
@Override
public OrderDto orderToDto(Order order) {
if ( order == null ) {
return null;
}
String name = null;
String product = null;
Integer price = null;
String address = null;
LocalDateTime orderedTime = null;
name = order.getName();
product = order.getProduct();
price = order.getPrice();
address = order.getAddress();
orderedTime = order.getOrderedTime();
String img = order.getProduct() + ".jpg";
OrderDto orderDto = new OrderDto( name, product, price, address, img, orderedTime );
return orderDto;
}
}
해당 코드를 보면 나는 interface로 메소드만 만들어줬을 뿐인데, Mapper 클래스가 만들어진 것을 확인할 수 있다.
OrderMapper orderMapper = Mappers.getMapper(OrderMapper.class);
// .. 생략
Order order = orderMapper.convertOrderDtoToEntity(orderDto);
위와 같이 OrderMapper를 활용해서 변환작업을 쉽게 처리할 수 있다.
출처
https://huisam.tistory.com/entry/mapStruct
https://mapstruct.org/documentation/stable/reference/html/
'web > Spring' 카테고리의 다른 글
[Spring Security] SecurityConfig 리팩토링 - WebSecurityConfigurerAdapter 상속 제거, Resource Filter Chain 설정 (0) | 2023.01.16 |
---|---|
[Spring] 도메인 객체 검증하는 방법 -> Validation (0) | 2022.11.18 |
[Spring] 페이징 성능 개선하기 3-2. 첫 페이지 조회 결과 캐시하기 (0) | 2022.07.21 |
[Spring] 페이징 성능 개선하기 3-1. 검색 버튼 사용시 페이지 건수 고정하기 (0) | 2022.07.20 |
[Spring] 페이징 성능 개선하기 2. 커버링 인덱스 사용하기 (0) | 2022.07.19 |
댓글 개