Request나 Response에 대한 VO, Entity와 분리하여 서비스와 컨트롤러 간에 데이터를 전달하기 위한 객체로 사용하는 DTO 등과 같은 객체들과 DB에 직접 접근하게 되는 Entity 간에 객체 형식을 용이하게 변환하기 위해 ModelMapper를 사용하게 된다. 이때 이를 사용하려면 기본 설정 작업이 필요하다.
우선 build.gradle에 아래와 같이 modelmapper 의존성을 추가해준다.
dependencies {
implementation group: 'org.modelmapper', name: 'modelmapper', version: '2.3.8'
}
그리고 ModelMapper를 @Bean으로 등록해주어야 이를 사용할 수 있다.
@Configuration
public class MapperConfig {
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}
다음으로 유틸리티로서 ModelMapperUtil을 만들어 변환하는 메서드를 자체적으로 만들어 사용하면 된다.
@RequiredArgsConstructor
public class ModelMapperUtil {
private final ModelMapper mapper;
public Entity convertDtoToEntity(Dto dto) {
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
Entity entity = mapper.map(dto, Entity.class);
return entity;
}
public Dto convertEntityToDto(Entity entity) {
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
Dto dto = mapper.map(entity, Dto.class);
return dto;
}
}
@Service
@RequiredArgsConstructor
public class ProfileServiceImpl implements ProfileService {
private final ModelMapperUtil modelMapperUtil;
@Transactional(readOnly = true)
@Override
public Dto getDto(String uuid) {
Entity entity = Optional.ofNullable(Repository.findByUuid(uuid)).orElseThrow(() -> {
throw new NoSuchElementException(messageUtil.getUuidNoSuchMessage(uuid)); });
Dto dto = modelMapperUtil.convertEntityToDto(entity);
return dto;
}
// 생략
}
그리고 단일 객체들 간 변환뿐만 아니라 아래와 같이 리스트와 리스트끼리 변환도 가능하다.
public List<Dto> mapEntityListToDtoList(List<Entity> entityList) {
List<Dto> dtoList = entityList.stream()
.map(entity -> mapper.map(entity, Dto.class))
.collect(Collectors.toList());
return dtoList;
}
이때 ModelMapper의 단점으로 @Entity에서도 @Setter가 필요하며, 이를 넣지 않으면 null 값으로 셋팅된다는 점이 있는데, AccessLevel을 PUBLIC에서 PRIVATE으로 변경하면 @Setter를 설정하지 않아도 된다.
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)
.setFieldMatchingEnabled(true);
return modelMapper;
}