ModelMapper란

단비·2023년 4월 24일
0

학습

목록 보기
15/66

ModelMapper란

  • 서로 다른 클래스의 값을 한번에 복사하게 도와주는 라이브러리
  • DTO와 Entity를 변환할 때 Getter, Setter을 이용할 경우 번거롭기 때문에 사용

modelmapper는 런타임시점에 리플렉션이 발생하므로 성능 저하가 매우 심함
컴파일 시점에 코드가 생성되는 mapstruct 사용하는 것을 권장


사용법

1. build.gradle

// https://mvnrepository.com/artifact/org.modelmapper/modelmapper
implementation group: 'org.modelmapper', name: 'modelmapper', version: '3.1.1'

2. Configuration

@Configuration
public class CustomModelMapper {
    private final ModelMapper modelMapper = new ModelMapper();

    @Bean
    public ModelMapper strictModelMapper() {
        modelMapper.getConfiguration()
                .setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper;
    }

    @Bean
    public ModelMapper standardModelMapper() {
        modelMapper.getConfiguration()
                .setMatchingStrategy(MatchingStrategies.STANDARD);
        return modelMapper;
    }

    @Bean
    public ModelMapper looseModelMapper() {
        modelMapper.getConfiguration()
                .setMatchingStrategy(MatchingStrategies.LOOSE);
        return modelMapper;
    }
}
  • STANDARD(default)
    • source와 destination 속성과 지능적으로 일치 시킴
    • 모든 destination 속성 이름 토큰이 일치해야 함
    • 모든 source 속성 이름은 일치하는 토큰이 하나 이상 있어야 함
    • 토큰들은 어떤 순서로든 일치될 수 있음
  • STRICT
    • 가장 엄격한 전략
    • source와 destination의 타입과 필드명이 같을 때만 변환
    • 의도하지 않은 매핑이 일어나는 것을 방지할 때 사용
    • 토큰들은 순서가 일치해야함
  • LOOSE
    • 가장 느슨한 전략
    • 속성 계층 구조가 매우 다른 source, destination 객체에 사용하는 데에 이상적
    • 토큰들은 어떤 순서로든 일치될 수 있음
    • 마지막 destination 필드명은 모든 토큰이 일치해야함
    • 마지막 source 필드명에는 일치하는 토큰이 하나 이상 있어야 함
    • 의도하지 않은 매핑이 될 확률이 높아 잘 사용하지 않음

Tokenizer

  • source 필드명과 destination의 필드명이 다를 때 사용
// source는 camelCase, destination은 under_score 형태일 때
modelMapper.getConfiguration()
           .setSourceNameTokenizer(NameTokenizers.CAMEL_CASE)
           .setDestinationNameTokenizer(NameTokenizers.UNDERSCORE);

Mapping 설정

  • 일치하지 않는 필드명이나 구조가 있더라도 필드들을 매핑시킬 수 있음
// User -> UserDTO 매핑설정
modelMapper.createTypeMap(User.class, UserDTO.class)
    	.addMapping(User::getName, UserDTO::setUserName) //addMapping
    	.addMapping(User::getEmail, UserDTO::setID)
    	.addMappings(mapping -> {  // 한번에 여러개 매핑.
       		mapping.map(source -> source.getGroupName(), UserDTO::setGroupName);
       		mapping.map(User::getUserNo, UserDTO::setNo);
    })

Converter를 이용한 데이터 가공

  • skip
    • destination 필드 중 매핑하고 싶지 않은 필드가 있을 때
    typeMap.addMappings(mapping -> {
            mapping.skip(UserDTO::setField);
    });
  • Null 필드 skip
    • null로 넘어오는 필드를 제외하고 업데이트 하고 싶을 때 (DTO -> Entity)
    • 모든 필드들에 대해 작동하기 때문에 특정 필드만 대상으로 skip하고 싶다면 아래의 Conditional Mapping을 사용
    modelMapper.getConfiguration().setSkipNullEnabled(true);
  • Conditional Mapping
    • 특정 필드가 null일 경우 매핑하고 싶지 않을 때 (DTO -> Entity)
    typeMap.addMappings(mapper -> mapper.when(
    		ctx -> 	
    			!ObjectUtils.isEmpty(ctx.getSource())
          ).map(UserDTO::getPassword, PersonDTO::setPassword));
profile
tistory로 이전! https://sweet-rain-kim.tistory.com/

0개의 댓글