반응형
MapStruct는 객체끼리 매핑을 해주는 유용한 기능이다.
간단하게 아래의 예로 사용법을 알아보자.
준비사항
- MapStruct는 Getter, Setter or builder 를 사용하기 때문에 lombok이 있으면 더욱 편리하게 사용할 수 있다.
- dependency 설정 시, Lombok 뒤에 MapStruct를 넣어줘야 정상적으로 실행 가능하다.
- 매핑에 진행하기 앞서, 반드시 매핑을 진행하는 두 객체는 아래와 같은 설정을 해야 한다.
- 반환 타입의 객체: Builder or Setter 필요 (반환 타입의 객체에 데이터를 설정해야 하기 때문)
- 파라미터 타입의 객체: Getter 필요(파라미터 객체의 데이터를 읽어야 하기 때문)
Category.java (Entity)
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "category")
public class Category {
@Id
private Integer id;
private String name;
private String upperId;
private String isLeaf;
private String useYn;
private Long depth;
}
CategoryDto.java (Dto)
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class CategoryDto {
private Integer categoryId;
private String categoryName;
private String upperId;
private String isLeaf;
private String useYn;
private Long depth;
}
위와 같이 Entity와 Dto가 있을 때 Entity를 Dto로 변환이 가능하다. (물론 반대로도 가능하다)
위에서 언급한 MapStruct를 이용하면 된다.
MapStruct의 흐름은 매핑되는 인터페이스를 규칙에 맞게 작성하면, 빌드할 때 자동으로 해당 인터페이스의 구현체가 생성된다.
import org.mapstruct.*;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface CategoryMapStruct {
@Mapping(target = "categoryId", source = "id")
@Mapping(target = "categoryName", source = "name")
CategoryDto toDtoFromEntity (Category category);
@Mapping(target = "id", source = "categoryId")
@Mapping(target = "name", source = "categoryName")
Category toEntityFromDto (CategoryDto categoryDto);
}
- 인터페이스를 작성할 때 신경써야하는 부분은 반환 타입과 파라미터 타입이다.
- 반환 타입과 파라미터 타입에 맞게 자동으로 매핑이 이루어진다.
- @Mapping
- MapStruct는 기본적으로 두 객체간의 같은 이름의 컬럼에 대해서 자동으로 매핑을 도와준다.
- 그렇다면, 서로 다른 이름을 가진 컬럼끼리 매핑을 할 수 없을 까?
- @Mapping 어노테이션을 이용해서 명시적으로 서로 다른 이름의 컬럼을 매핑하는 규칙을 설정할 수 있다.
- target은 반환 타입 객체의 컬럼 이름, source는 파라미터 타입 객체의 컬럼 이름이다.
- toDtoFromEntity 를 보면, 반환되는 타입은 Dto 타입이고, 파라미터 타입은 Entity인 것을 볼 수 있다.
즉, toDtoFromEntity 은 Entity를 Dto로 변경해주는 함수이다. - 이렇게 작성하고 정상적으로 build가 실행된다면, 해당 인터페이스의 이름 + Impl 이라는 구현체가 자동으로 생성된다.
(위 예제에서는 CategoryMapStructImpl 이 될 것이다.) - @Mapper unmappedTargetPolicy : 매핑되지 않는 컬럼이 있을 때에 대한 설정
- ReportingPolicy.IGNORE : 매핑되지 않는 컬럼이 있는 경우, 무시하는 설정
- ReportingPolicy.WARN : 빌드 중 매핑되지 않는 컬럼이 있는 경우, 경고로 알려주는 설정
- ReportingPolicy.ERROR : 빌드 중 매핑되지 않는 컬럼이 있는 경우, 빌드가 실패하도록 하는 설정
Collection Mapping
import org.mapstruct.*;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface CategoryMapStruct {
@Named("toDtoFromEntity")
@Mapping(target = "categoryId", source = "id")
@Mapping(target = "categoryName", source = "name")
CategoryDto toDtoFromEntity (Category category);
@Named("toEntityFromDto")
@Mapping(target = "id", source = "categoryId")
@Mapping(target = "name", source = "categoryName")
Category toEntityFromDto (CategoryDto categoryDto);
// Collection 간에 매핑을 진행할 때 아래와 같이 @IterableMapping 어노테이션을 사용한다.
@IterableMapping(qualifiedByName = "toDtoFromEntity")
List<CategoryDto> toDtoListFromEntityList (List<Category categoryList);
@IterableMapping(qualifiedByName = "toEntityFromDto")
List<Category> toEntityListFromDtoList (List<CategoryDto> categoryDtoList);
}
- Collection 간의 매핑 규칙은 @IterableMapping를 사용해야 한다.
(만약, 두 객체간의 컬럼 이름이 모두 동일하다면 정상적으로 매핑) - @Named 어노테이션으로 매핑 규칙을 설정하고, 위 소스처럼 @IterableMapping으로 규칙을 넣어줘야 Collection 간의 매핑이 가능하다.
반응형
'BE > Java' 카테고리의 다른 글
[BAEKJOON] 18405번 : 경쟁적 전염 (JAVA) (1) | 2024.06.09 |
---|---|
[JMeter] JMeter 사용 및 설치 방법 (0) | 2024.05.06 |
[Java 8] Stream, 데이터 리듀싱 (1) | 2024.03.24 |
[Java 8] 람다식과 함수형 인터페이스 (0) | 2024.03.10 |
[Java] Reflection? (0) | 2023.12.25 |