Contents
MyBatis์˜ Result Maps
   May 15, 2023     7 min read

Result Maps

๐Ÿ‘‰resultMap์ด๋ž€?

resultMap์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ ์ž‘์„ฑ๋˜๋Š” JDBC์ฝ”๋“œ๋ฅผ ๋Œ€๋ถ€๋ถ„ ์ค„์—ฌ์ฃผ๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค.

JOIN ๋งคํ•‘๊ณผ ๊ฐ™์€ ๋ณต์žกํ•œ ์ฝ”๋“œ๋Š” ๋งŽ์€ ์–‘์˜ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

ํ•˜์ง€๋งŒ resultMap์€ ๊ฐ„๋‹จํ•œ ๊ตฌ๋ฌธ์—์„œ๋Š” ๋งคํ•‘์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ณ  ๋ณต์žกํ•œ ๊ตฌ๋ฌธ์—์„œ ๊ด€๊ณ„๋ฅผ ์„œ์ˆ ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•˜๋‹ค.


๐Ÿ‘‰DB์˜ ์นผ๋Ÿผ๋ช…๊ณผ ํ”„๋กœํผํ‹ฐ๋ช…์ด ๊ฐ™์„ ๊ฒฝ์šฐ

  • resultMap์„ ์“ฐ์ง€์•Š์€ ์˜ˆ์ œ
<select id="selectUsers" resultType="map">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>
  • JavaBean ์˜ˆ์ œ
    • property : id, username, hashedPassword
package com.someapp.model;
public class User {
  private int id;
  private String username;
  private String hashedPassword;

  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getUsername() {
    return username;
  }
  public void setUsername(String username) {
    this.username = username;
  }
  public String getHashedPassword() {
    return hashedPassword;
  }
  public void setHashedPassword(String hashedPassword) {
    this.hashedPassword = hashedPassword;
  }
}
  • ์œ„์˜ ์ฟผ๋ฆฌ(select)์— ์นผ๋Ÿผ๋ช…์ด ์ •ํ™•ํžˆ ์ผ์น˜ํ•œ๋‹ค. โ†’ ๋”ฐ๋ผ์„œ ์ž๋ฐ”๋นˆ์€ HashMap๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋งค์šฐ ์‰ฝ๊ฒŒ ResultMap์— ๋งคํ•‘๋  ์ˆ˜ ์žˆ๋‹ค.
<select id="selectUsers" resultType="com.someapp.model.User">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

๐Ÿ‘‰DB์˜ ์นผ๋Ÿผ๋ช…๊ณผ ํ”„๋กœํผํ‹ฐ๋ช…์ด ๊ฐ™์ง€ ์•Š์„ ๊ฒฝ์šฐ

  1. ์นผ๋Ÿผ๋ช…๊ณผ ํ”„๋กœํผํ‹ฐ๋ช…์ด ๋‹ค๋ฅด๋‹ค๋ฉด SQL๊ตฌ๋ฌธ์— ๋ณ„์นญ์„ ์ง€์ •ํ•œ๋‹ค.
<select id="selectUsers" resultType="User">
  select
    user_id             as "id",
    user_name           as "userName",
    hashed_password     as "hashedPassword"
  from some_table
  where id = #{id}
</select>
  1. resultMap์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name"/>
  <result property="password" column="hashed_password"/>
</resultMap>
    • id : userResultMap
    • type : User.java
  • resultMap="userResultMap" ์œผ๋กœ ์ฐธ์กฐํ•œ๋‹ค.
<select id="selectUsers" resultMap="userResultMap">
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>

๐Ÿ‘‰๋ณต์žกํ•œ ๊ฒฐ๊ณผ๋งคํ•‘

<!-- ๋งค์šฐ ๋ณต์žกํ•œ ๊ตฌ๋ฌธ -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
  select
       B.id as blog_id,
       B.title as blog_title,
       B.author_id as blog_author_id,
       A.id as author_id,
       A.username as author_username,
       A.password as author_password,
       A.email as author_email,
       A.bio as author_bio,
       A.favourite_section as author_favourite_section,
       P.id as post_id,
       P.blog_id as post_blog_id,
       P.author_id as post_author_id,
       P.created_on as post_created_on,
       P.section as post_section,
       P.subject as post_subject,
       P.draft as draft,
       P.body as post_body,
       C.id as comment_id,
       C.post_id as comment_post_id,
       C.name as comment_name,
       C.comment as comment_text,
       T.id as tag_id,
       T.name as tag_name
  from Blog B
       left outer join Author A on B.author_id = A.id
       left outer join Post P on B.id = P.blog_id
       left outer join Comment C on P.id = C.post_id
       left outer join Post_Tag PT on PT.post_id = P.id
       left outer join Tag T on PT.tag_id = T.id
  where B.id = #{id}
</select>
  • ResultMap ์˜ˆ์ œ
<!-- Very Complex Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="Author">
    <id property="id" column="author_id"/>
    <result property="username" column="author_username"/>
    <result property="password" column="author_password"/>
    <result property="email" column="author_email"/>
    <result property="bio" column="author_bio"/>
    <result property="favouriteSection" column="author_favourite_section"/>
  </association>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection>
</resultMap>
  • resultMap
    • constructor - ์ธ์Šคํ„ด์Šคํ™”๋˜๋Š” ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— ๊ฒฐ๊ณผ๋ฅผ ์‚ฝ์ž…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
      • idArg - ID์ธ์ž. ID์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋Š” ์ „๋ฐ˜์ ์œผ๋กœ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.
      • arg - ์ƒ์„ฑ์ž์— ์‚ฝ์ž…๋˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฒฐ๊ณผ
    • result - ํ•„๋“œ๋‚˜ ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ์— ์‚ฝ์ž…๋˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฒฐ๊ณผ
    • association - ๋ณต์žกํ•ฉ ํƒ€์ž…์˜ ์—ฐ๊ด€๊ด€๊ณ„. ๋งŽ์€ ๊ฒฐ๊ณผ๋Š” ํƒ€์ž…์œผ๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค.
      • ์ค‘์ฒฉ๋œ ๊ฒฐ๊ณผ ๋งคํ•‘ - resultMap ์Šค์Šค๋กœ์˜ ์—ฐ๊ด€๊ด€๊ณ„
    • collection - ๋ณต์žกํ•œ ํƒ€์ž…์˜ ์ปฌ๋ ‰์…˜
      • ์ค‘์ฒฉ๋œ ๊ฒฐ๊ณผ ๋งคํ•‘ - resultMap ์Šค์Šค๋กœ์˜ ์—ฐ๊ด€๊ด€๊ณ„
    • discriminator - ์‚ฌ์šฉํ•  resultMap์„ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ์‚ฌ์šฉ
      • case - ๋ช‡ ๊ฐ€์ง€ ๊ฐ’์— ๊ธฐ์ดˆํ•œ ๊ฒฐ๊ณผ ๋งคํ•‘
        • ์ค‘์ฒฉํ•œ ๊ฒฐ๊ณผ ๋งคํ•‘ - ์ด ๊ฒฝ์šฐ ๋˜ํ•œ ๊ฒฐ๊ณผ๋งคํ•‘ ์ž์ฒด์ด๊ณ  ์ด๋Ÿฌํ•œ ๋™์ผํ•œ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋งŽ์ด ํฌํ•จํ•˜๊ฑฐ๋‚˜ ์™ธ๋ถ€resultMap์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
      ์†์„ฑ์„ค๋ช…
      id๊ฒฐ๊ณผ๋งคํ•‘์„ ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์œผ๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์—์„œ ์œ ์ผํ•œ ์‹๋ณ„์ž
      typeํŒจํ‚ค์ง€๋ฅผ ํฌํ•จํ•œ ์ž๋ฐ” ํด๋ž˜์Šค๋ช…์ด๋‚˜ ํƒ€์ž…๋ณ„์นญ
      autoMapping์ด ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋ฉด Mybatis๋Š” ๊ฒฐ๊ณผ๋งคํ•‘์„ ์ž๋™๋งคํ•‘์œผ๋กœ ์ฒ˜๋ฆฌํ• ์ง€ ๋ง์ง€๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด ์†์„ฑ์€ autoMappingBehavior๋ผ๋Š” ์ „์—ญ์„ค์ •์„ ๋ฎ๋Š”๋‹ค. ๋””ํดํŠธ๋Š” unset์ด๋‹ค.

๐Ÿ‘‰id, result

<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
  • id์™€ result ๋ชจ๋‘ ํ•œ ๊ฐœ์˜ ์ปฌ๋Ÿผ์„ ํ•œ๊ฐœ์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์˜ ํ•„๋“œ์— ๋งคํ•‘ํ•œ๋‹ค.

  • id์™€ result์˜ ์ฐจ์ด์ 
    • id๊ฐ’์€ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๋น„๊ตํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ตฌ๋ถ„์ž ํ”„๋กœํผํ‹ฐ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ์ ์ด ์ฐจ์ด์ ์ด๋‹ค. ์ด ๋ถ€๋ถ„์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค์ง€๋งŒ ํŠนํžˆ ์บ์‹œ์™€ ๋‚ดํฌ๋œ(nested)๊ฒฐ๊ณผ ๋งคํ•‘(์กฐ์ธ ๋งคํ•‘)์˜ ๊ฒฝ์šฐ์— ๋” ๊ทธ๋ ‡๋‹ค.
  • id์™€ result ์—˜๋ฆฌ๋จผํŠธ ์†์„ฑ
์†์„ฑ์„ค๋ช…
property๊ฒฐ๊ณผ ์ปฌ๋Ÿผ์— ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•œ ํ•„๋“œ๋‚˜ ํ”„๋กœํผํ‹ฐ. ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ๊ฐ€ ํ•ด๋‹น ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•œ๋‹ค๋ฉด ๊ทธ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์‚ฌ์šฉ๋  ๊ฒƒ์ด๋‹ค. ๋ฐ˜๋ฉด์— MyBatis๋Š” ํ•ด๋‹น ์ด๋ฆ„์ด ํ•„๋“œ๋ฅผ ์ฐพ์„ ๊ฒƒ์ด๋‹ค. ์ (.) ํ‘œ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ๋งคํ”„๋กœํผํ‹ฐ ๊ฒ€์ƒ‰์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
์˜ˆ) โ€œusernameโ€๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งคํ•‘๋  ์ˆ˜ ์žˆ๊ฑฐ๋‚˜ โ€œaddress.street.numberโ€์ฒ˜๋Ÿผ ๋ณต์žกํ•˜๊ฒŒ ๋งคํ•‘๋  ์ˆ˜๋„ ์žˆ๋‹ค.ย 
columnย 
javaTypeย 
jdbcTypeย 
typeHadnlerย 

๐Ÿ”—์ฐธ์กฐ

[MyBatis โ€“ ๋งˆ์ด๋ฐ”ํ‹ฐ์Šค 3๋งคํผ XML ํŒŒ์ผ](https://mybatis.org/mybatis-3/ko/sqlmap-xml.html#result-maps)