Backend/Database

[Mybatis] 결과를 코틀린 DTO로 받을 때 프로퍼티 순서가 중요한 경우

mopil 2023. 10. 6. 14:49
반응형

프로젝트에서 복잡한 쿼리를 위해 보통 QueryDSL이나 MyBatis를 사용한다.

 

MyBatis를 사용하는 경우 select 결과를 dto로 바로 받을 수 있는데, 이때 간혹

 

코틀린의 dto 클래스 (data class)의 프로퍼티 선언 순서와 select 절의 값 순서가 동일해야만 매핑되는 경우가 있다.

 

이런 경우는 어떤 경우이며 왜 그런지 살펴보자 (데이터베이스는 오라클을 기준)

 

# 예시 세팅

다음과 같은 SQL을 가정해보자

SELECT A_V AS firstValue, B_V AS secondValue
FROM table;

 

그리고 마이바티스로 이를 받아올 DTO는 다음과 같다고 해보자

data class Dto(
    val firstValue: String,
    val secondValue: String
)

만약 이런 경우면 select 절 값 순서와 data class 프로퍼티 순서가 동일해서 정상 매핑이 가능하다.

 

 

data class Dto(
    val secondValue: String, // 순서를 바꾼다
    val firstValue: String
)

근데 이렇게 선언 순서를 변경하면, 부적합한 변환이 요청됨 에러가 발생한다.

 

 

data class Dto(
    val secondValue: String = "", // 순서를 바꾸고, 기본값을 주면 매핑 가능
    val firstValue: String = ""
)

이런 경우에 기본값을 지정하면 또 매핑이 잘 된다.

 

이런 이유는 MyBatis의 DTO매핑 전략 때문에 그렇다.

 

 

# MyBatis DTO 매핑 전략

MyBatis는 select 결과를 자바 POJO 클래스로 매핑할 때, 다음과 같은 로직을 따른다.

 

1. 기본생성자만 존재하는 경우 : 모든 프로퍼티가 null로 매핑

2. 기본생성자 + 칼럼 별칭 (alias)를 설정한 경우 : 정상 매핑

3. 모든 필드 생성자 : 정상 매핑 (단, 순서가 중요해짐)

4. 기본생성자 + 일부 필드 생성자 : 일부 필드에 대해서만 매핑

 

 

따라서, 코틀린의 data class의 경우

data class Dto(
    val secondValue: String, // 순서를 바꾼다
    val firstValue: String
)

이 경우는 모든 필드 생성자만 있는 경우 (2) 이므로, 순서가 중요하고

 

data class Dto(
    val secondValue: String = "", // 순서를 바꾸고, 기본값을 주면 매핑 가능
    val firstValue: String = ""
)

기본생성자 + 칼럼 별칭 케이스 (3) 이므로 순서 상관 없이 매핑이 가능하다.

반응형