ABOUT ME

-

오늘 방문자
-
어제 방문자
-
전체
-
  • model mapping 라이브러리 Mapstruct
    JAVA 2021. 7. 8. 23:02

     

    Mapstruct란?

    모델간 맵핑을 쉽게 해주는 라이브러이다    ex) entity <-> dto

    -컴파일 시점에 맵핑클래스를 생성함(그래서 매우 좋음 바로바로 확인가능)

    -ModelMapper 보다 맵핑 성능이 훨씬 좋음

     

     

    1.  라이브러리 추가

    mapstruct만 추가해주면된다.

    dependencies {
    	implementation 'org.springframework.boot:spring-boot-starter-validation'
    	implementation 'org.springframework.boot:spring-boot-starter-web'
    	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'
    	implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:2.1.1.RELEASE'
    	compileOnly 'org.projectlombok:lombok'
    	annotationProcessor 'org.projectlombok:lombok'
    	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    	annotationProcessor "org.mapstruct:mapstruct-processor:1.3.1.Final"
    	runtimeOnly 'com.h2database:h2'
    	
        // mapstruct!! 추가
    	implementation 'org.mapstruct:mapstruct:1.3.1.Final'
            
    	testImplementation('org.springframework.boot:spring-boot-starter-test') {
    		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    	}
    }

     

     

    2. 예제 DTO , Entity 생성

    2-1 DTO

    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import lombok.ToString;
    
    @ToString
    @Getter @Setter
    @NoArgsConstructor // 기본생성자 필수!
    @AllArgsConstructor // 테스트코드 작성을 위해 추가
    public class UserDto {
    
        private String nameModel;
    
        private int ageModel;
    
        private String addrModel;
    
    }

     

    2-2 Entity  

    실제 Entity로 만들진 않았지만, Entity 역할을 하는 model로 테스트 진행 예정

    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import lombok.ToString;
    
    @ToString
    @Getter @Setter
    @NoArgsConstructor // 기본 생성자 필수!
    @AllArgsConstructor // 테스트코드 작성을 위해 추가
    public class User {
    
        private String name;
    
        private int age;
    
        private String addr;
    
    }

     

     

    3. mapper 인터페이스 생성*중요

    source : 맵핑시킬 멤버 필드명

    target : 맵핑되어질 멤버 필드명

    ignor : 해당 멤버필드는 맵핑하지 않음

     

    참고 : 멤버 필드명이 양쪽이 모두 같다면 속성명시는 생략가능.

     

    import com.example.test.test.dto.UserDto;
    import com.example.test.test.dto.User;
    import org.mapstruct.Mapper;
    import org.mapstruct.Mapping;
    import org.mapstruct.factory.Mappers;
    
    
    @Mapper // mapstruct를 사용하기 위해 선언
    public interface UserMapper {
    	
        //UserMapper를 상속받아 구현체가 작성됨 , build 폴더가보면 확인가능. UserMapperImpl이 생성됨
        UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); 
    	
        // Entity를 DTO로 맵핑 
        @Mapping(source = "name", target ="nameModel")
        @Mapping(source = "age", target ="ageModel")
        @Mapping(source = "addr", target ="addrModel")
        UserDto userEntityToUserDto(User user);
    	
        // DTO를 Entity로 맵핑
        @Mapping(source = "nameModel", target = "name")
        @Mapping(source = "ageModel", target = "age")
        @Mapping(source = "addrModel", target = "addr")
        User userDtoToUserEntity(UserDto userDto);
    	
        // 특정 컬럼을 제외하고 맵핑 (ignore속성)
        @Mapping(target ="addr", ignore = true)
        @Mapping(target = "name" , source = "nameModel")
        @Mapping(target = "age" , source = "ageModel")
        User userDtoToEntityAndIgnore(UserDto userDto);
    
    }

     

    4. 테스트 코드 작성

    import com.example.test.test.dto.User;
    import com.example.test.test.dto.UserDto;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    
    
    class UserMapperTest {
    
        @Test
        public void DTO를_Entity로_맵핑() {
            UserDto userDto = new UserDto("민", 20, "서울");
    
            User user = UserMapper.INSTANCE.userDtoToUserEntity(userDto);
    
            System.out.println(">>>>> userDto = " + userDto);
            System.out.println(">>>>> user = " + user);
    
            Assertions.assertEquals("민", user.getName());
            Assertions.assertEquals(20, user.getAge());
            Assertions.assertEquals("서울", user.getAddr());
        }
    
        @Test
        public void Entity를_DTO로_맵핑() {
            User user = new User("민", 20, "서울");
    
            UserDto userDto = UserMapper.INSTANCE.userEntityToUserDto(user);
    
            System.out.println(">>>>> user = " + user);
            System.out.println(">>>>> userDto = " + userDto);
    
            Assertions.assertEquals("민", userDto.getNameModel());
            Assertions.assertEquals(20, userDto.getAgeModel());
            Assertions.assertEquals("서울", userDto.getAddrModel());
        }
    
        @Test
        public void 주소필드는_무시하고_맵핑() {
            UserDto userDto = new UserDto("민", 20, "서울");
    
            User user = UserMapper.INSTANCE.userDtoToEntityAndIgnore(userDto);
    
            System.out.println(">>>>> userDto = " + userDto);
            System.out.println(">>>>> user = " + user);
    
            Assertions.assertEquals("민", user.getName());
            Assertions.assertEquals(20, user.getAge());
            Assertions.assertEquals(null, user.getAddr());
        }
    
    }

     

    5.결과 성공

    댓글

Designed by Tistory.