[Spring] Modelmapper에서의 매핑 관련 Troubleshooting

JunH·2023년 3월 15일

결론부터 두괄식으로 작성해보자면,

"ModelMapper는 해당 클래스의 기본 생성자를 이용해 객체를 생성하고 setter를 이용해 매핑을 한다."

https://lob-dev.tistory.com/entry/%EA%B0%9D%EC%B2%B4-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0-%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C-%EB%A7%A4%ED%95%91-vs-MapStruct-vs-ModelMapper

해당 블로그의 내용을 일부 인용하자면 이렇다.

Modelmapper는 일반적으로 setter를 사용한다. (개인적으로 Setter를 통해 모든 필드를 열어놓는 행위를 싫어한다.)

본인도 이 생각에 동의하는 바

@Entity
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@Getter
@Table(name = "USER", indexes = @Index(name = "i_email", columnList = "email"))
public class User extends BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    private Long id;
    //password
    @Column(nullable = false)
    private String password;
    @Column(unique = true,nullable = false)
    private String email;

    private String name;
    private String phone;
    private String address;
    private String level;

    @OneToOne(fetch = FetchType.LAZY)
    private Order order;
}

엔티티는 DB정보와 직결되는 객체라고 생각하는 바, 프로젝트 시작부터 생성자와 Setter를 전부 틀어막아서 불변 객체로 만들고싶어했다.

public void signUp(SignupRequest request) {
        if (isExistsEmail(request.getEmail())) {
            throw new DuplicatedIdException("Same id exists email: " + request.getEmail());
        }
        UserDTO encryptedUser = encryptUser(request);
        User userTemp = modelMapper.map(encryptedUser, User.class);
        userRepository.save(userTemp);
    }

결과를 보자, 분명 ModelMapper으로 매칭을 시도했건만 전부 null이 뜨는 모습이다.

@Configuration
@RequiredArgsConstructor
public class ModelMapperConfig {
    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();

        /*연결 전략 : 같은 타입의 필드명이 같은 경우만 동작
        *
        * */
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE).setSkipNullEnabled(true).setFieldMatchingEnabled(true)
                .setFieldAccessLevel(AccessLevel.PRIVATE);;
        return modelMapper;
    }
}

해당 방법으로 해결하자 딱히 @Setter 같은 어노테이션이나 setter를 추가하지 않고도 잘 매핑되는 결과를 볼 수 있었다.

+추가 "modelmapper Unable to make field private final java.time.LocalDate java.time.LocalDateTime.date accessible: module java.base does not "opens java.time" to unnamed module" 의 경우 LocalDateTime 타입과 Date 타입을 갖는 필드간 매칭할때 벌어지는 오류였다.

0개의 댓글