[MyBatis] 객체 안의 객체 매핑하기 (ResultMap과 DTO)
객체 안의 객체 매핑하기
- https://mybatis.org/mybatis-3/ko/sqlmap-xml.html# - 복잡한 결과매핑 섹션 부터 참조.
- 읽어 보면 알겠지만, 연관(Association)을 위한 중첩된 Select 는 N+1 Selects problem으로 인해 추천하지 않는다.
- `` LEFT OUTER JOIN``을 활용한 관계를 위한 내포된 결과(Nested Results) 방법을 사용하는 것을 권장하고 있다
DTO를 사용하면 굳이 객체 안의 객체 매핑 할 필요 없이, DTO에서 flatten해서 받아도 된다.
어차피 쿼리는 `` LEFT OUTER JOIN``을 사용한다면 컬럼을 flatten 해서 가져오게 된다.
따라서 [`` ResultMap - DTO - Model``] 변환의 어느 단계에서든 flatten -> groupping 하는 과정이 필요하다.
silver bullet은 없으므로, 따라서 상황과 취향에 맞게 선택하면 된다.
ResultMap에서 flatten한 상태로 받아오고, DTO로 넘기면서 groupping하는 방법
- mybatis ResultMap을 하나 정의하고 여기서 객체 안의 객체(DTO 안의 DTO) 형태로 묶어주는 방법
- 보통 이 방법이 DTO 재사용성, 쿼리 재사용성 측면에서는 더 낫다.
ResultMap 없이 DTO로 flatten 한 상태로 받아오고, Domain Model로 넘기면서 groupping 하는 방법
- 하지만 재사용성이 전부일까? 아래와 같은 상황을 생각해보자.
- A와 B는 n:1 관계. A에 FK 있음.
- tbl_a와 tbl_b는 N+1 Select 이슈를 피하기 위해 join해서 한 번에 가져와야 함
- tbl_a.bno, tbl_b.bno 같은 이름의 컬럼이 양측 모두 존재
- Domain Model A와 B 모두 businessNumber라는 필드를 가지고 있음 (둘 다 tbl_a.bno로 초기화 되어야 함)
- 이 때 flatten DTO를 사용한다면
- DTO.businessNumber 필드를 1개만 가지고 있기 때문에 Domain Model A와 Domain Model B가 같은 tbl_a.bno로 초기화 될 수 있음.
- 그러나 resultMap을 사용한다면
- `` DtoA.businessNumber = tbl_a.bno; DtoB.businessNumber = tbl_b.bno`` 또는 여기서 둘 다 tbl_a.bno로 초기화 할 수는 있지만 이러한 내용이 쿼리에 숨겨져 있다면 더 추적하기 어렵다. (DtoB의 필드는 tbl_b 컬럼에 대응 될 것이라고 예상하기 때문)
- Domain Model B를 초기화 할 때는, businessNumber만 DtoA의 것을 사용하고 나머지는 DtoB의 것을 사용해야 한다.
- 상대적으로 복잡해진다.
'Java Stack > Persistence' 카테고리의 다른 글
Spring JDBC와 JdbcOperations (0) | 2023.08.10 |
---|---|
[MyBatis] Cache (0) | 2022.03.08 |
redis - java persistence (0) | 2020.03.10 |
[Spring] DB 관련 : Mybatis (3) | 2020.03.04 |