Post

(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의 것을 사용해야 한다.
    • 상대적으로 복잡해진다.

This post is licensed under CC BY 4.0 by the author.