ModelMapper 도입과 Setter

leverest96·2022년 12월 19일
0

Trouble Shooting

목록 보기
1/20
post-thumbnail

문제 인지

DTO → Entity 변환과 Entity → DTO 변환을 좀 더 편하게 하기 위해 ModelMapper를 도입하려 했으나, Setter를 사용해야 하는 상황에 직면했다.

문제 원인 #1

Setter를 사용할 경우 여러 문제점이 뒤따라 올 수 있어 가급적이면 사용을 지양하고자 했으나, ModelMapper가 기본적으로 Public 메서드를 이용하여 변환을 수행하기 때문에 Setter를 열어주어야 하는 상황에 직면했다.

해결 방법 #1

@Bean
public ModelMapper modelMapper() {
    final ModelMapper modelMapper = new ModelMapper();

    modelMapper.getConfiguration()
            .setFieldMatchingEnabled(true)
            .setFieldAccessLevel(AccessLevel.PRIVATE);

    return modelMapper;
}

ModelMapper의 필드 변환을 활성화하고, 필드 접근 제한자 레벨을 Private으로 변경하여 문제를 해결할 수 있었다.

이때, modelMapper의 내부 인자는 모두 object여야한다.
예를 들어, String을 넣으면 오류가 발생한다.

문제 원인 #2

public class AccountCreationRequestDto {
    @NotNull
    private final Long profileId;

    @NotBlank
    @Email
    private final String email;

    @NotBlank
    private final String password;
}

클라이언트의 요청 파라미터를 처리하기 위해 별도의 DTO를 정의해놓고, 필요한 시점에 ModelMapper를 이용해 Entity로 변환해서 사용하도록 설계를 하였다.

@Entity
public class Account extends Timestamp {
    public static final int VERIFICATION_CODE_MAX_LENGTH = 6;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @JoinColumn(name = "profile_id", nullable = false)
    @OneToOne(fetch = FetchType.LAZY)
    private Profile profile;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private Boolean verificationState;

    @Column(length = VERIFICATION_CODE_MAX_LENGTH)
    private String verificationCode;
}

하지만 Account Entity의 verificationState 필드처럼 반드시 설정해 주어야 하지만 DTO에는 없는 경우가 있어, ModelMapper를 이용해 변환한 이후 Setter를 이용해 추가적으로 설정을 해주어야 하는 문제가 생겼다.

해결 방법 #2

@Builder
public Account(final Long id, final Profile profile, final String email, final String password, final Boolean verificationState, final String verificationCode) {
    setProfile(profile);

    this.id = id;
    this.email = email;
    this.password = password;
    this.verificationState = verificationState;
    this.verificationCode = verificationCode;
}

void setProfile(final Profile profile) {
    if (this.profile != null) {
        this.profile.setAccount(null);
    }

    this.profile = profile;

    if (profile != null) {
        profile.setAccount(this);
    }
}

Entity에 반드시 설정되어야 하는 필드지만 DTO에는 없어서 ModelMapper만으로는 해결되지 않는 경우, ModelMapper를 사용하는 대신 Builder 패턴을 이용하여 직접 설정해 주기로 하였다.

Organized by Igoc
https://velog.io/@hope1213/Setter-%EC%82%AC%EC%9A%A9%EC%9D%84-%EC%99%9C-%EC%A7%80%EC%96%91%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C
https://yooooonnf.tistory.com/2

profile
응애 난 애기 개발자

0개의 댓글