Mybatis를 이용해 1:N 관계 테이블에서 값을 가져오는 방법에는 크게 3가지가 있다.
우선 첫 번째 방법은,
Domain 클래스가 실제 테이블처럼 관계를 맺고 있는 테이블의 id 값을 가지도록 한 후, Mybatis에서는 이 두 테이블을 Join해서 데이터를 가져오는 방법이다.
public class Post {
private int postId;
...
private int boardId; // fk
}
남은 두 방법은 위의 방법과는 달리, Board 클래스가 멤버변수로 Post 객체의 리스트를 갖는 형태로 구성된다.
public class Board {
private int boardId;
...
private List<Post> posts;
}
이렇게 구성해주면, 게시판이 게시물 리스트를 가진다는 점에서 실제 세계를 반영하는 객체지향 관점에 좀 더 알맞다.
그리고 위와 같은 클래스 구조를 가질 때, MyBatis에서는 두 가지 방법으로 Post를 포함하는 Board 데이터를 가져온다.
Nested Select
<resultMap id="boradResult" type="net.krespo.mybatis.Board">
<id property="boardId" column="board_id"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<collection property="comments" column="comment_id" javaType="java.util.ArrayList" ofType="net.krespo.mybatis.Comment" select="getCommentListById"/>
</resultMap>
<select id="getBoardById" resultMap="boardResult">
SELECT boardid, title, content FROM board WHERE boardid = #{boardid}
</select>
<select id="getCommentListById" resultType="net.krespo.mybatis.Comment">
SELECT commentid, boardid, writer, content FROM comment WHERE boardid = #{boardId}
</select>
그러나 이렇게 Nested Select를 하는 경우, getBoardById를 한 번 호출하면 getCommentListById가 N번 호출되어, 결과적으로 select 쿼리가 N+1번 실행되는 결과를 낳는다.
cf) commentList를 얻는 질의해서 인자를 두 개 넘겨주고 싶은 경우
<collection property="comments" column="{boardId=board_id,writer=writer}" javaType="java.util.ArrayList" ofType="net.krespo.mybatis.Comment" select="getMyCommentListById"/>
<select id="getMyCommentListById" parameterType="java.util.Map" resultType="net.krespo.mybatis.Comment">
SELECT id, writer, content FROM comment WHERE boardid = #{boardId} AND writer = #{writer}
</select>
(이 경우 parameterType을 Map으로 지정해줘야한다.)
Nested Result
<resultMap id="boardResult" type="net.krespo.mybatis.Board">
<id property="boardId" column="board_id"/> <!-- property는 도메인 클래스의 멤버변수명과 일치, column은 테이블의 컬럼명과 일치 -->
<result property="title" column="title"/>
<result property="content" column="content"/>
<collection property="comments" column="comment_id" javaType="java.util.ArrayList" ofType="net.krespo.mybatis.Comment">
<id property="commentId" column="comment_id"/> <!-- Comment 클래스의 멤버 변수와 property 값이 일치 -->
<result property = "writer" column="writer"/>
<result property = "content" column="content" />
</collection>
</resultMap>
<!-- mysql -->
<select id="findItemsBill" resultMap="menuInfo">
SELECT m.id menuId, m.name menuName, m.price menuPrice,
opt.id optionId, opt.name optionName, opt.price optionPrice
FROM MENU m LEFT OUTER JOIN OPTION opt
ON (m.id = opt.menu_id)
WHERE m.id IN (<foreach collection="list" item="menu" separator=",">#{menu.menuId}</foreach>)
AND opt.id IN (
<foreach collection="list" item="menu" separator=",">
<foreach collection="menu.options" item="option" separator=",">
#{option.optionId}
</foreach>
</foreach>)
</select>
<resultMap id="empResultMap" type="com.test.domain.emp">
<id property="seq" colunm="seq" />
<result property="empNm" colunm="empNm" />
<result property="empId" colunm="orgId" />
<collection property="orgList" resultMap="orgResultMap"/>
</resultMap>
<resultMap id="orgResultMap" type="com.test.domain.org">
<id property="empId" colunm="orgId" />
<result property="empNm" colunm="orgNm" />
</resultMap>
<select id="selectEmp" parameterType="hashmap" resultMap="empResultMap">
SELECT *
FROM EMP A
LEFT OUTER JOIN ORG B ON A.ORG_ID = B.ORG_ID
</select>
참고 자료
https://deveric.tistory.com/74
https://mybatis.org/mybatis-3/ko/sqlmap-xml.html