myBatis 1:N 의 결과를 select 하기

Posted 2013. 12. 9. 02:28

이전 iBatis에서의 방법과는 많이 달라진 myBatis의 모습. 그중에서 적응이 쉽지 않았던 것 중에 one to many 즉, 1:N  데이터의 처리였다.

iBatis에서의 처리방법(여러개의 테이블을 조인한 결과는 어디에 담지?) 은 N+1 의 문제를 않고 있었던 내용이었다.

 

myBatis로 넘어오면서 이부분에 대한 고민의 흔적이 있었던것 같다.

myBatis에서의 on to many는  collection을 이용하는 방법이다.

 

예제를 통해 알아보자. myBatis 공식사이트에서 언급하고 있는 블로그 관련 예제이다.

 

우선 블로그글 한개당 여러개의 태그가 나온다고 한다면 이전 iBatis에서는

 

select

blog_id,

blog_title,

(select post_id, subject from post  where blog_id = a.blog_id) as post_list

from blog a

 

와 같은 형태의 쿼리를 실행해야만 했다. 당연히 성능면에서 문제가 되는 쿼리다.

 

myBatis에서 이를 사용하려면 아우터 조인을 이용한 해결방법이다.

공식사이트를 보면서 제일 헤맸던 부분이 키에 대한 처리였다. 즉 <id property"" column=""/> 부분이다.

 

이전 iBatis에서의 기억때문에 더 헷갈렸는지도 모른다.

 

Class Blog {

 

   private List<Post> postList;

   public List<Post> getPostList(){...}

 

   public void setPostList(....){}

}

 

Class Post{

  private int blog_id;

  private int post_id;

}

 

 

<select id="selectBlog" parameterType="int" resultMap="blogResult">
  select
  B.blog_id ,
  B.title as blog_title,
  P.post_id,
  P.subject as post_subject,
  P.body as post_body,
  from Blog B
  left outer join Post P on B.blog_id = P.blog_id
  where B.blog_id = #{id}
</select>

 

 

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <result property="body" column="post_body"/>
  </collection>
</resultMap>

post_id를 기준으로 한 subQuery의 결과를 리턴하기 때문에 이전 iBatis의 기억 때문에 post_id 대신에 blog_id를 넣고 한참이나 해멨었다. 계속 결과값이 1개만 나와서...

 

 

자세한 참고사항은 아래를 참고하자.

http://mybatis.github.io/mybatis-3/ko/sqlmap-xml.html