티스토리 뷰
내 프로젝트에는 Member, Product, Cart domain이 존재한다
Cart는 Member를 N : 1 & Product를 1 : 1로 가지고 있는 Entity이다
이 상황에서 Cart를 응답하기 위한 CartResponse로 변환하고 GenericMapper를 그대로 쓰면 어떻게 될까?
당연히 Cart의 속성 member와 product가 그대로 나간다
변화 가능성이 큰 Entity로 응답하지 않기 위해 DTO 형태로 만들어 반환하는 것인데 현재의 DTO는 이를 위반한다
기존의 GenericMapper를 이용하며 member와 product도 dto 형태로 만들어 반환해줘야한다
약간의 커스텀 작업이 필요하다 우선 CartResponse에 Entity가 아닌 DTO 형태를 명시해준다
GenericMapper를 그대로 상속받으면서 Service 계층에서 사용할 메서드
toDto, toEntity, updateFromDto를 오버라이딩 해준다
먼저 스프링 컨테이너가 찾을 수 있도록 @Mapper(componentModel = "spring")을 적어주도록 하고
여기서 핵심은 @Mappings 부분이다
매핑할 속성의 이름이 같다면 MapStruct가 알아서 매핑해주지만 이름이 다른 경우 지정해주어야 한다
toDto의 경우 member -> memberResponse 형태이므로 source / target을 맞춰주고 toEntity는 반대로 맞춰준다
updateFromDto를 오버라이딩할 때 기본적으로 @BeanMapping과 @MappingTarget이 붙지 않는다
Test를 돌리면 updateFromDto에서 예외가 발생해 터지기 때문에
GenericMapper에서 해당 부분을 찾아와 다시 붙여주도록 한다
@Mapper(componentModel = "spring")
public interface CartResponseMapper extends GenericMapper<CartResponse, Cart> {
@Override
@Mappings({
@Mapping(source = "member", target = "memberResponse"),
@Mapping(source = "product", target = "productResponse")})
CartResponse toDto(Cart cart);
@Override
@Mappings({
@Mapping(source = "memberResponse", target = "member"),
@Mapping(source = "productResponse", target = "product")})
Cart toEntity(CartResponse cartResponse);
@Override
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
@Mappings({
@Mapping(source = "memberResponse", target = "member"),
@Mapping(source = "productResponse", target = "product")})
void updateFromDto(CartResponse dto, @MappingTarget Cart entity);
}
이렇게 하면 기존 Mapper들과 똑같이 작동하며 원하는 DTO 형태로 반환된다
'Spring > Spring Framework' 카테고리의 다른 글
[Test] 기묘한 병렬 테스트 (0) | 2021.12.06 |
---|---|
[Test] JPA DataIntegrityViolationException 발생 테스트 복구 (0) | 2021.11.19 |
[Test] 깨지는 테스트 어떻게 복구할까? (3) | 2021.09.24 |
[MapStruct] MapStruct의 update 기능 사용 주의 (0) | 2021.09.20 |
[AOP] 소요 시간 측정 AOP class level에 적용하기 (0) | 2021.09.09 |