DevBoi

[Java] Mapstruct Spring 적용하기 본문

Language/[Java]

[Java] Mapstruct Spring 적용하기

HiSmith 2023. 6. 14. 22:16
반응형

MapStruct에 대한 적용을 다시 공부해보려고한다.

새로운 기능들도 조금 나온 것같고, 예전에 써서 기억도 안나서, 다시 공부할겸 정리를 한다.

 

1. Mapstruct 

해당 기술은, Entity와 Dto간의 매핑을 지원하는 라이브러리다.

getter,setter를 남발하여, 직접 구현하는 것보다. 라이브러리를 쓰는 것이 좋다.

유사하게는 MdoelMapper, 성능은 이게 더 빠르다.

 

Mapstruct 생성

@Data
@AllArgsConstructor
public class MemberResponse {
  private String name;
  private String id;
}
@Data
@AllArgsConstructor
public class Member {
  private String name;
  private String id;
}
@Mapper
public interface GenericMapper {
  GenericMapper mapper = Mappers.getMapper(GenericMapper.class);
  MemberResponse converMember(Member member);
}
@RestController
public class MemberController {

  @RequestMapping("/member")
  public String mapperTest(){
    Member member = new Member("id","name");
    MemberResponse res = GenericMapper.mapper.converMember(member);
    return res.getId();
  }
}

 

해당으로 MEMBER -> MEMBERRESPONSE변환을 확인 할 수 있다.

추가적으로, 컬럼이 다를때는 아래와 같다.

@Data
@AllArgsConstructor
public class MemberResponse {
  private String name_MemberRes;
  private String id_MemberRes;
}
@Data
@AllArgsConstructor
public class Member {
  private String name_Member;
  private String id_Member;
}

 

해당 케이스 에서는 이렇다.

@Mapper
public interface GenericMapper {
  GenericMapper mapper = Mappers.getMapper(GenericMapper.class);
  @Mapping(source = "id_Member", target = "id_MemberRes")
  @Mapping(source = "name_Member", target = "name_MemberRes")
  MemberResponse converMember(Member member);
}

 

자, 그러면 이제 제네릭하게 바꿔보자

public  interface GenericMapper<D,E> {
  GenericMapper mapper = Mappers.getMapper(GenericMapper.class);
  @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
  E convertBeanMapping(D dto, @MappingTarget E entity);
}

 

해당 제네릭 인터페이스를 우선 정의 한다.

그리고 해당 제네렉 구현체에 대한 필요한 구현체를 직접 구현한다.

예시로,member,memberResponse에 대한 예시를 만들 것 이다.

 

@Mapper(componentModel = "spring")
public interface MemberMapper extends GenericMapper<Member, MemberResponse>{
}

 

위 처럼 구현체로 만들었는데, compontModel로 하게 되면, Spring에 맞는 구현체로 generated 폴더 하위에 자동으로 생성해준다.

querydsl설정 및 제공 서비스가 비슷하다.

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-06-14T22:11:55+0900",
    comments = "version: 1.4.1.Final, compiler: IncrementalProcessingEnvironment from gradle-language-java-7.6.1.jar, environment: Java 11.0.16 (Oracle Corporation)"
)
@Component
public class MemberMapperImpl implements MemberMapper {

    @Override
    public MemberResponse convertBeanMapping(Member dto, MemberResponse entity) {
        if ( dto == null ) {
            return null;
        }

        if ( dto.getName() != null ) {
            entity.setName( dto.getName() );
        }
        if ( dto.getId() != null ) {
            entity.setId( dto.getId() );
        }

        return entity;
    }
}

해당 자동 생성된, 코드를 보면, 자동으로 component로 등록을 해주는 소스를 생성해주는 것을 알 수 있다.

해당 부분을 사용하면 된다.

@RequestMapping("/member")
  public String mapperTest(){
    Member member = new Member("id","name");
    MemberResponse res = new MemberResponse("id_2","name_2");
    res = memberMapper.convertBeanMapping(member,res);

    return res.getId();
  }

 

실제로 사용할때 코드이다.

물론 컬럼 명이 다른 경우에는, @Mapping을 추가로 하여, source,target에 대한 정의를 미리 해줘야 가능하다.

이건 위에서 설명이 나왔으니 귀찮아서 패스 하도록 하자.

 

 

무튼 이렇게 하면 대략적인 설계도 끝이 난다.

또한 null에대한 properties 매핑 전략도 설정할 수 있다.

각각을 다르게 설정할 수도있으니, 간편하게 관리할 수 있다.

 

 

이만 끗 -

반응형