(loop (print (eval (read))))

;;닭집을 차리기 위한 여정

마이바티스 활용하기

매핑하기.

사실, 모든 내용은 마이바티스 공홈에 다 있다. 그런데 흔히 잘 안보고 지나치는 기능 두개에 대해서 얘기해보려고 한다.
columnPrefix 와 discrimantor 가 그것이다.

이들을 써서 맵핑하는 방법이다.

1
2
3
4
5
6
7
8
9
10
11
<resultMap type="exp.model.Post" id="Post">
<id column="ID" property="id"/>
<result column="NAME" property="name"/>
<result column="TITLE" property="title"/>
<result column="CONTENT" property="content"/>
<association property="author" columnPrefix="USR_" resultMap="exp.repo.UserMapper.User"/>
<discriminator javaType="exp.var.PostType" column="type">
<case value="PUBLIC" resultType="exp.model.PublicPost"/>
<case value="PRIVATE" resultType="exp.model.PrivatePost"/>
</discriminator>
</resultMap>

association 엘리먼트에 걸린 내용을 잘 보면 columnPrefix 어트리뷰트에 USR_ 이라고 명시하고 다른 결과맵으로 맵핑하도록 해놓았다.
그리고 discriminatorjavaType 으로 enum 타입을 적시하고 어떤 타입으로 맵핑할 것인지 정한다. 물론 Post의 하위 타입이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<select id="select" resultMap="Post">
<![CDATA[
SELECT
post.ID,
post.TYPE,
post.TITLE,
post.CONTENT,
usr.ID AS USR_ID,
usr.TYPE AS USR_TYPE,
usr.NAME AS USR_NAME,
usr.AGE AS USR_AGE
FROM
post
JOIN
USR ON post.USR_ID = USR.ID
]]>
</select>

columnPrefix

테이블명과 자바클래스명을 일치시킨다면, comlumnPrefix를 이용해서 모든 alias 를 멤버명과 동일하게 일치시킬 수 있다. 예를들어,
Post 클래스에 comments 필드가 있다면 columnPrefixCOMMENTS_ 로 주고 collection 으로 매핑하면 된다.
(나는 이를 위해서라도 테이블명에 복수형을 붙이지 않는다. 테이블명을 복수형으로 붙이는건 (예를들어 users, posts..) 간지난다는거 빼고 좋은게 없는듯.

더 좋은것은 이 columnPrefix 가 선언된 하위 resultMap 은 재귀적으로 적용된다는 것. 예를들어 COMMENTS_AUTHOR_ID 같은 alias를 해석할수 있다는 것.

하지만 이 방법은 캐쉬를 적용하기에 좋지 않다.

discriminator

Post 클래스는 어쩔 수 없이 abstract 클래스여서는 안된다.
그런 제약이 있기는 해도, select 한 번으로 각 하위타입으로 매핑해서 (또한 재귀적으로) 조회할 수 있다는건 큰 매력이다.
참고로 이렇게 조회한 Post 의 리스트는 google-guava 라이브러리의 filter 메서드같은 함수형 접근과 아주 궁합이 잘 맞는다.

일전에 언급했던 템플릿 패턴과 같이 쓰면 표현력이 대폭 상승하게 된다.