[Spring Boot] MapStruct @Mapping(target="",source="")

어디든 배우자·2023년 11월 23일

문제 발생 전

Post Entity에 썸네일과 디테일 이미지를 연관관계 맵핑을 해 둔 상태.

@Entity
public class PostInfo {
  	
  	'''
  
	@OneToMany(mappedBy = "postInfo", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	@JsonIgnore
    private List<PostDetailImage> postDetailImages;

    @OneToMany(mappedBy = "postInfo", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonIgnore
    private List<PostThumbnailImage> postThumbnailImages;

}

Post Detail를 조회하는 Mapper를 먼저 생성.

@Mapper
public interface PostMapper {

    PostMapper INSTANCE = Mappers.getMapper(PostMapper.class);

    PostDTO toPostDTO(PostInfo postInfo,
                      List<PostDetailImage> postDetailImages,
                      List<PostThumbnailImage> postThumbnailImages);

}

그 이후 코드 재사용을 위해 Post Detail Mapper에 Stream()을
사용하여 Post List를 조회하는 코드 구축.

return postInfos.stream()
                .map(postInfo -> postMapper.toPostDTO(
                        postInfo,
                        postInfo.getPostDetailImages(),
                        postInfo.getPostThumbnailImages())
                )
                .collect(Collectors.toList());

문제 발생

Post Entity에 Post Review 연관관계 맵핑 추가하였고,
데이터를 조회하던 중 문득, List에는 Post Detail이 필요없지 않은가? 생각을 함.
지금 연관관계 맵핑이 LAZY로 설정되어 있음.
그래서 Post List 조회 매개 변수인 Post Detail를 null로 전달함.

return postInfos.stream()
                .map(postInfo -> postMapper.toPostDTO(
                        postInfo,
                        new ArrayList<>(),
                        postInfo.getPostThumbnailImages())
                )
                .collect(Collectors.toList());

하지만 계속해서 Post Detail이 조회됐음.
원인을 찾아보니 MapStruct을 사용하여 Compile을 하여 생성되는
파일에 문제가 있었음.

@Override
public PostDTO toPostDTO(PostInfo postInfo, 
                         List<PostDetailImage> postDetailImages, 
                         List<PostThumbnailImage> postThumbnailImages) {
  if ( postInfo == null && postDetailImages == null && postThumbnailImages == null ) {
    return null;
  }

  PostDTO postDTO = new PostDTO();

  if ( postInfo != null ) {
    
    '''//중간코드 생략
    
    List<PostDetailImage> list = postInfo.getPostDetailImages();
    if ( list != null ) {
      postDTO.setPostDetailImages( new ArrayList<PostDetailImage>( list ) );
    }
    List<PostThumbnailImage> list1 = postInfo.getPostThumbnailImages();
    if ( list1 != null ) {
      postDTO.setPostThumbnailImages( new ArrayList<PostThumbnailImage>( list1 ) );
    }
  }

  return postDTO;
}

위에 코드를 보면 내가 전달한 매개변수 Post Detail을 사용 안하고
postInfo에서 조회를 하고 있었음.
분명 이 코드를 작성할 때 하이버네이트 쿼리문을 확인 했었음.
저 부분을 바꾸려면 Mapper 인터페이스에서 뭔가를 수정해야함.
정답은 은근 쉬웠음.

@Mapper
public interface PostMapper {

    PostMapper INSTANCE = Mappers.getMapper(PostMapper.class);

    @Mapping(target = "postDetailImages", source = "postDetailImages")
    PostDTO toPostDTO(PostInfo postInfo,
                      List<PostDetailImage> postDetailImages,
                      List<PostThumbnailImage> postThumbnailImages);

}

@Mapping을 활용했음. 저 어노테이션을 간략하게 설명하자면

target의 Post Detail 이건 PostDTO에 있는 값이라 생각

source의 Post Detail 이건 toPostDTO에 매개변수를 지칭

따라서 
DTO에 있는 postDetailImages의 값을 
매개변수 postDetailImages로 값을 채울께~

우선 1차적 해결하고싶은거 해결. 근데 문제를 또 발견함.
Handler dispatch failed; nested exception is java.lang.StackOverflowError
이 에러를 만남. 이건 다음글에서 해결해보겠다.

profile
다 흡수하기.

0개의 댓글