본문 바로가기
스프링과 JPA 기반 웹 어플리케이션 개발/1부 (개발환경, 회원가입, 로그인, 계정설정)

29. ModelMapper 적용

by Backchus 2020. 4. 22.

http://modelmapper.org/

 

ModelMapper - Simple, Intelligent, Object Mapping.

Why ModelMapper? The goal of ModelMapper is to make object mapping easy, by automatically determining how one object model maps to another, based on conventions, in the same way that a human would - while providing a simple, refactoring-safe API for handli

modelmapper.org

  • 객체의 프로퍼티를 다른 객체의 프로퍼티로 맵핑해주는 유틸리티

의존성 추가

<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>2.3.6</version>
</dependency>

 

ModelMapper를 빈으로 등록

package me.weekbelt.studyolle.config;

@Configuration
public class AppConfig {

    // 기존 코드

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        // 필드명이 언더스코어가 아니라면 하나의 변수명으로 설정
        modelMapper.getConfiguration()
                .setDestinationNameTokenizer(NameTokenizers.UNDERSCORE)
                .setSourceNameTokenizer(NameTokenizers.UNDERSCORE);
        return modelMapper;
    }
}

Notification의 필드를 보면 CamelCase로 변수명이 길게 선언이 되어있기때문에 modelMapper의 기본설정으로는 매핑이 잘 되지 않는다. 따라서 변수명이 언더스코어가 아닐경우 하나의 변수명으로 설정하기위해 위처럼 설정을 추가한다. 

package me.weekbelt.studyolle.settings;

@Data
@NoArgsConstructor
public class Notifications {

    private boolean studyCreatedByEmail;

    private boolean studyCreatedByWeb;

    private boolean studyEnrollmentResultByEmail;

    private boolean studyEnrollmentResultByWeb;

    private boolean studyUpdatedByEmail;

    private boolean studyUpdatedByWeb;

    public Notifications(Account account) {
        this.studyCreatedByEmail = account.isStudyCreatedByEmail();
        this.studyCreatedByWeb = account.isStudyCreatedByWeb();
        this.studyEnrollmentResultByEmail = account.isStudyEnrollmentResultByEmail();
        this.studyEnrollmentResultByWeb = account.isStudyEnrollmentResultByWeb();
        this.studyUpdatedByEmail = account.isStudyUpdatedByEmail();
        this.studyUpdatedByWeb = account.isStudyUpdatedByWeb();
    }
}

 

 

ModelMapper를 이용하여 AccountService 리팩토링

package me.weekbelt.studyolle.account;

@Transactional
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {

    // 기존 코드 ......
    
    private final ModelMapper modelMapper;

    // 기존 코드 ......
    

    public void updateProfile(Account account, Profile profile) {
        modelMapper.map(profile, account);    
        accountRepository.save(account);
    }

    // 기존 코드 ......

    public void updateNotifications(Account account, Notifications notifications) {
        modelMapper.map(notifications, account);
        accountRepository.save(account);
    }
}

 

Notification, Profile DTO 에서 Account를 받는 생성자를 삭제한다. 이 DTO들의 생성은 SettingsController에서 처리한다.

package me.weekbelt.studyolle.settings;

import lombok.Data;

@Data
public class Notifications {

    private boolean studyCreatedByEmail;

    private boolean studyCreatedByWeb;

    private boolean studyEnrollmentResultByEmail;

    private boolean studyEnrollmentResultByWeb;

    private boolean studyUpdatedByEmail;

    private boolean studyUpdatedByWeb;

}
package me.weekbelt.studyolle.settings;

@Data
public class Profile {

    @Length(max = 35)
    private String bio;

    @Length(max = 50)
    private String url;

    @Length(max = 50)
    private String occupation;

    @Length(max = 50)
    private String location;

    private String profileImage;

}

 

SettingsController 리팩토링

package me.weekbelt.studyolle.settings;

@RequiredArgsConstructor
@Controller
public class SettingsController {

    // 기존 코드 .......
    
    private final ModelMapper modelMapper;

    // 기존 코드 ........

    @GetMapping("/settings/profile")
    public String updateProfileForm(@CurrentUser Account account, Model model) {
        model.addAttribute(account);
        model.addAttribute(modelMapper.map(account, Profile.class));       // 수정
        return "settings/profile";
    }

    // 기존 코드 .........

    @GetMapping("/settings/notifications")
    public String updateNotificationsForm(@CurrentUser Account account, Model model) {
        model.addAttribute(account);
        model.addAttribute(modelMapper.map(account, Notifications.class));  // 수정
        return "settings/notifications";
    }

    // 기존 코드 ........
}

 

 

참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#

 

스프링과 JPA 기반 웹 애플리케이션 개발 - 인프런

이 강좌에서 여러분은 실제로 운영 중인 서비스를 스프링, JPA 그리고 타임리프를 비롯한 여러 자바 기반의 여러 오픈 소스 기술을 사용하여 웹 애플리케이션을 개발하는 과정을 학습할 수 있습니다. 이 강좌를 충분히 학습한다면 여러분 만의 웹 서비스를 만들거나 취직에 도움이 될만한 포트폴리오를 만들 수 있을 겁니다. 활용 웹 개발 프레임워크 및 라이브러리 Java Spring Spring Boot Spring Data JPA Thymeleaf 온라인 강의 스

www.inflearn.com