MapStruct란?
- Entity에서 Dto(Data Transfer Object)로 변환하고자 할때 매핑을 지원하는 라이브러리.
- 계층간 데이터 교환을 할때 DTO를 변환하는 것을 각 계층에서 하게되면 의존성이 생길 수 있고, 관심사의 분리가 어려워지게 된다.
- 매핑을 toEntity(),toDto() 와 같은 메서드로 직접 구현해도 되지만,
- 변환하고자 하는 Dto가 증가할 수록 반복적이고, 불필요한 코드를 작성해야한다.
- 코드 작성시 실수를 하게 되면, 개발 생산성이 저하한다.
등의 문제가 발생할 수 있다.
환경 설정
build.gradle에 다음과 같이 의존성을 추가한다.
implementation 'org.mapstruct:mapstruct:1.4.1.Final'
implementation 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
implementation "org.projectlombok:lombok:1.18.16"
annotationProcessor "org.mapstruct:mapstruct-processor:1.4.1.Final"
annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0"
annotationProcessor "org.projectlombok:lombok:1.18.16"
Mapper 구현
내가 작성한 Mapper는 다음과 같다.
@Mapper(componentModel = "spring")
public interface ProblemMapper {
@Mapping(source="link", target = "link")
@Mapping(target = "id", ignore = true)
@Mapping(target = "tagList", ignore = true)
@Mapping(target = "reviewList", ignore = true)
Problem toEntity(ProblemRequestDto requestDto);
ProblemResponseDto toDto(Problem problem);
}
어노테이션을 살펴보면,
- @Mapper(componentModel = "spring")
- @Mapper 어노테이션으로 Mapstruct 클래스라는 것을 스프링에게 알린다.
- 빌드시 @Mapper 인터페이스를 ProblemMapperImpl과 같은 형태로 구현체를 생성한다.
- componentModel 속성을 "spring"으로 하게되면 생성되는 Impl은 스프링이 빈으로 관리한다. -> @Component
- @Mapping(source="link", target = "link")
- source에는 내가 변환하고자할 객체(ProblemRequestDto)의 매핑 변수를 넣고,
- target에는 내가 변환하고 싶은 객체(Problem)의 매핑 변수를 넣는다.
- source에는 있으나, target에서는 변환하지 않아도 되면 해당 target에 추가 속성으로 ignore = true를 설정한다.
- source에도 있고, target에도 있으나 변환하고싶지 않을경우 source,target,ignore를 모두 설정하면 된다.
빌드를 하게 되면 다음과 같은 구현체가 생성된다.
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2023-01-23T14:57:19+0900",
comments = "version: 1.4.2.Final, compiler: javac, environment: Java 11.0.16 (Oracle Corporation)"
)
@Component
public class ProblemMapperImpl implements ProblemMapper {
@Override
public Problem toEntity(ProblemRequestDto requestDto) {
if ( requestDto == null ) {
return null;
}
ProblemBuilder problem = Problem.builder();
problem.title( requestDto.getTitle() );
problem.link( requestDto.getLink() );
problem.step( requestDto.getStep() );
return problem.build();
}
@Override
public ProblemResponseDto toDto(Problem problem) {
if ( problem == null ) {
return null;
}
ProblemResponseDtoBuilder problemResponseDto = ProblemResponseDto.builder();
problemResponseDto.id( problem.getId() );
problemResponseDto.title( problem.getTitle() );
problemResponseDto.link( problem.getLink() );
problemResponseDto.step( problem.getStep() );
List<Review> list = problem.getReviewList();
if ( list != null ) {
problemResponseDto.reviewList( new ArrayList<Review>( list ) );
}
List<ProblemTag> list1 = problem.getTagList();
if ( list1 != null ) {
problemResponseDto.tagList( new ArrayList<ProblemTag>( list1 ) );
}
return problemResponseDto.build();
}
}
'🍃Spring' 카테고리의 다른 글
[Spring DB] MyBatis 사용하기 (0) | 2023.01.29 |
---|---|
[Spring DB] 테스트 - 트랜잭션 (0) | 2023.01.29 |
[Spring DB] JDBC Template 사용하기 (0) | 2023.01.29 |
[Spring] Spring이란? (0) | 2023.01.28 |
[Spring] DTO를 사용하는 이유 (0) | 2023.01.22 |