Mapstruct

배세훈·2022년 6월 3일
0

Spring

목록 보기
36/38

MapStruct란?

MapStruct는 Entity와 DTO 간에 변환할 때 자동으로 변환되도록 도와주는 라이브러리입니다.

매핑해줄 클래스에는 setter가 있어야 하고 매핑이 되는 클래스에는 getter가 있어야 사용 가능합니다. (Users Entity -> UserDTO로 변경시 entity쪽에 getter, dto쪽에 setter가 존재해야합니다)

또한 추가적인 인터페이스를 작성해야 하고 gradle을 통해 작성된 인터페이스에 맞는 구현 클래스도 만들어져 있어야 합니다

MapStruct의 장점(ModelMapper와 비교)

  • 매핑 속도가 빠름
  • 명시적임(변수들이 어떻게 매핑되는지 확인 가능)
  • 컴파일 단계에서 에러 확인 가능
  • 변수 명의 제약이 덜함

예제

build.gradle 설정

dependencies{
	implementation 'org.mapstruct:mapstruct:1.4.2.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
  • 주의사항으로 Lombok과 같이 적용할 경우 Lombok 순서가 더 먼저/위에 있어야 합니다.

Entity / DTO

  • 사용자(Users)와 게시판(board) 1:N관계
// Users Entity
import lombok.Getter;
import lombok.Setter;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
@Getter @Setter
public class Users {
    @Id
    private String userId;
    @Column
    private String userName;
}
// Users DTO
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class UserDto { 
    private String userId;
    private String userName;
}
// Board Entity
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter @Setter
public class Board {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String title;

    @Column
    private String content;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private Users user;

}
// Board DTO
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BoardDto {
    private Long id;
    private String title;
    private String content;
    private String userId;
}

Default Mapper 생성(필수 X)

import java.util.List;

public interface StructMapper<D, E>{
	D toDto(E entity);
    E toEntity(D dto);
    List<D> toDtoList(List<E> entityList);
    List<E> toEntityList(List<D> dtoList);
}

연관관계가 없는 Entity인 경우(Users)

UsersMapper 생성
import com.feign.feignserver.dto.UserDto;
import com.feign.feignserver.entity.Users;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UsersMapper extends StructMapper<UserDto, Users>{
	UsersMapper INSTANCE = Mappers.getMapper(UsersMapper.class);
    
    /**
    	extends를 안할 경우 다음 코드 추가
        UserDto toDto(Users user);
        Users toEntity(UserDto userDto);
        List<UserDto> toDtoList(List<Users> userList);
        List<Users> toEntityList(List<UserDto> userDtoList);
    **/
}
  • gradle -> build 실행

  • 해당 위치에 파일 생성되는지 확인(UsersMapperImpl.java)

import com.feign.feignserver.dto.UserDto;
import com.feign.feignserver.entity.Users;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.processing.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-06-03T15:15:54+0900",
    comments = "version: 1.4.2.Final, compiler: IncrementalProcessingEnvironment from gradle-language-java-7.4.1.jar, environment: Java 11.0.2 (Oracle Corporation)"
)
public class UsersMapperImpl implements UsersMapper {

    @Override
    public UserDto toDto(Users entity) {
        if ( entity == null ) {
            return null;
        }

        UserDto userDto = new UserDto();

        userDto.setUserId( entity.getUserId() );
        userDto.setUserName( entity.getUserName() );

        return userDto;
    }

    @Override
    public Users toEntity(UserDto dto) {
        if ( dto == null ) {
            return null;
        }

        Users users = new Users();

        users.setUserId( dto.getUserId() );
        users.setUserName( dto.getUserName() );

        return users;
    }

    @Override
    public List<UserDto> toDtoList(List<Users> entityList) {
        if ( entityList == null ) {
            return null;
        }

        List<UserDto> list = new ArrayList<UserDto>( entityList.size() );
        for ( Users users : entityList ) {
            list.add( toDto( users ) );
        }

        return list;
    }

    @Override
    public List<Users> toEntityList(List<UserDto> dtoList) {
        if ( dtoList == null ) {
            return null;
        }

        List<Users> list = new ArrayList<Users>( dtoList.size() );
        for ( UserDto userDto : dtoList ) {
            list.add( toEntity( userDto ) );
        }

        return list;
    }
}

연관관계가 있는 Entity인 경우(Board)

BoardMapper 생성
import com.feign.feignserver.dto.BoardDto;
import com.feign.feignserver.entity.Board;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface BoardMapper extends StructMapper<BoardDto, Board> {
	BoardMapper INSTANCE = Mappers.getMapper(BoardMapper.class);
    
    @Overrid
    @Mapping(source = "user.userId", target = "userId") // 변수명이 다를 경우 source = Entity, target = Dto
    //@Mapping(target = "userId", constant = "hong" // 임의로 값을 입력하고 싶을 때
    BoardDto toDto(Board board);
}
profile
성장형 인간

0개의 댓글