웹개발/Web
편리한 객체 간 매핑을 위한 MapStruct 사용법
slown
2023. 8. 28. 00:43
MapStruct는 Java bean 유형 간의 매핑 구현을 단순화하는 코드 생성기입니다.
MapStruct 의 장점
컴파일시 설정된 압식으로 오류를 확인할 수 있다.(코드 생성시)
리플렉션을 사용하지 않기 때문에 매핑 속도가 빠르다.
디버깅이 쉽다.
생성된 매핑코드를 눈으로 직접 확인할 수 있다.
MapStruct의 사용법
1. gradle을 통해서 라이브러리를 주입한다.
//map struct
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final"
2. 엔티티에서 데이터를 옮길 dto클래스를 작성한다.
@Getter
@Setter
@Builder
@AllArgsConstructor
public class MemberRequest {
@NotBlank(message = "회원 이름을 입력해주세요.")
private String userName;
@NotBlank(message = "패스워드를 입력해주세요.")
private String password;
@NotBlank(message = "회원 나이를 입력해주세요.")
private Integer userAge;
@NotBlank(message = "회원 이메일을 입력해주세요.")
private String userEmail;
private Role role;
}
@Getter
@ToString
@Builder
@AllArgsConstructor
public class MemberResponse {
private Long id;
private String userName;
private String password;
private Integer userAge;
private String userEmail;
private Role role;
private LocalDateTime createdTime;
private LocalDateTime updatedTime;
}
3. Mapper 인터페이스를 작성해서 Entity -> Dto 그리고 반대되는 경우의 메소드를 작성을 한다.
//1.componentModel은 map struct에 자동으로 주입
@Mapper(componentModel = "spring")
public interface MemberMapper {
MemberMapper INSTANCE = Mappers.getMapper(MemberMapper.class);
//entity -> dto
MemberResponse entityToDto(Member member);
//dto -> entity
//맵핑을 하는 과정에서 제외를 하고 싶은 컬럼은 ignore를 true
@Mapping(target = "id",ignore = true)
@Mapping(target = "createdTime",ignore = true)
@Mapping(target = "updatedTime",ignore = true)
Member dtoToEntity(MemberRequest memberRequest);
}
Mapper 인터페이스에 @Mapper 어노테이션을 붙이면 MapStruct가 자동으로 MemberMapper의 구현체를 생성해줍니다.
위에서 사용된 MemberMapper INSTANCE = Mappers.getMapper(MemberMapper.class) 는 매퍼 클래스에서 MemberMapper를 찾을 수 있도록 하는 방법입니다. 매퍼 interface에서 위와 같이 Instance를 선언해주면 매퍼에 대한 접근이 가능합니다. 매핑하려는 객체는 필드값이 동일하기 때문에, 구현 코드를 작성 또는 수정하지 않고 쉽게 매핑할 수 있습니다.
그 후에 gradle로 빌드를 하고 나면 자동으로 해당 메소드에 관련된 객체가 구현이 됩니다.
@Component
public class MemberMapperImpl implements MemberMapper {
public MemberMapperImpl() {
}
public MemberResponse entityToDto(Member member) {
if (member == null) {
return null;
} else {
MemberResponse.MemberResponseBuilder memberResponse = MemberResponse.builder();
memberResponse.id(member.getId());
memberResponse.userName(member.getUserName());
memberResponse.password(member.getPassword());
memberResponse.userAge(member.getUserAge());
memberResponse.userEmail(member.getUserEmail());
memberResponse.role(member.getRole());
memberResponse.createdTime(member.getCreatedTime());
memberResponse.updatedTime(member.getUpdatedTime());
return memberResponse.build();
}
}
public Member dtoToEntity(MemberRequest memberRequest) {
if (memberRequest == null) {
return null;
} else {
Member.MemberBuilder member = Member.builder();
member.userName(memberRequest.getUserName());
member.password(memberRequest.getPassword());
member.userAge(memberRequest.getUserAge());
member.userEmail(memberRequest.getUserEmail());
member.role(memberRequest.getRole());
return member.build();
}
}
}
그리고 위의 코드가 제대로 작동을 하는지를 확인하기 위해서 테스트 코드를 작성을 하면 이러하다.
@Test
@DisplayName("Map Struct Entity->Dto")
public void EntityToDto(){
Member member = MemberFactory.member();
MemberResponse response = MemberMapper.INSTANCE.entityToDto(member);
assertThat(response).isNotNull();
assertThat(response.getId()).isEqualTo(member.getId());
assertThat(response.getUserName()).isEqualTo(member.getUserName());
assertThat(response.getPassword()).isEqualTo(member.getPassword());
assertThat(response.getUserEmail()).isEqualTo(member.getUserEmail());
assertThat(response.getUserAge()).isEqualTo(member.getUserAge());
assertThat(response.getCreatedTime()).isEqualTo(member.getCreatedTime());
assertThat(response.getUpdatedTime()).isEqualTo(member.getUpdatedTime());
}
@Test
@DisplayName("Map Struct Dto->Entity")
public void DtoToEntity(){
MemberRequest memberRequest = MemberFactory.request();
Member member = MemberMapper.INSTANCE.dtoToEntity(memberRequest);
assertThat(member).isNotNull();
assertThat(member.getUserName()).isEqualTo(memberRequest.getUserName());
assertThat(memberRequest.getPassword()).isEqualTo(member.getPassword());
assertThat(memberRequest.getUserAge()).isEqualTo(member.getUserAge());
}
[참고]