mybatis - low-hill/Knowledge GitHub Wiki

mybatis

Dynamic SQL

choose(when, otherwise)

foreach

<where>
  <choose>
    <when test="ids == null">
      <if test="name != null">
        displayNm LIKE CONCAT('%', #{name}, '%')
      </if>
    </when>
    <otherwise>
      AND id IN ( <foreach collection="ids" item="id" separator=",">#{id}</foreach> )
    </otherwise>
  </choose>
</where>

insert duplicate update with foreach

on duplicate key update column์— values๋ฅผ ์‚ฌ์šฉ

insert into user(name, gender, email)
values
<foreach collection="members" item="item" separator=",">
(
    #{item.name}
  , #{item.gender}
  , #{item.email}
)
</foreach>
on duplicate key update
  name = values(name)
  gender = values(gender)
  email = values(email)

useGeneratedKeys: ์ž๋™ ์ƒ์„ฑ ํ‚ค ๊ฐ€์ ธ์˜ค๊ธฐ

useGeneratedKeys=โ€trueโ€ ๋กœ ์„ค์ •ํ•˜๊ณ  keyProperty์— ์ž๋™์ƒ์„ฑํ‚ค ์ปฌ๋Ÿผ์„ ์…‹ํŒ…

<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>
  • ๋‹ค์ค‘ ๋ ˆ์ฝ”๋“œ ์ž…๋ ฅ ์‹œ
<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>

selectKey

  • keyProperty: selectKey๊ตฌ๋ฌธ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์…‹ํŒ…๋  property(resultType[class]์˜ ๋ฉค๋ฒ„๋ณ€์ˆ˜์™€ ์ผ์น˜)
  • resultType: ๊ฒฐ๊ณผ์˜ ํƒ€์ž…
  • order: BEFORE / AFTER
    • BEFORE: selectKey๊ตฌ๋ฌธ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋จผ์ € ์‹คํ–‰
    • AFTER: selectKey๊ตฌ๋ฌธ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋งˆ์ง€๋ง‰์— ์‹คํ–‰
<insert id="addUser" parameterType="User">
  <selectKey keyProperty="userId,userName" resultType="User" order="AFTER">
    SELECT USER_ID AS userId
         , USER_NAME AS userName
    FROM USER
    ORDER BY USER_ID DESC
    LIMIT 1
  </selectKey>
  INSERT INTO USER(col1, ...)
  VALUES (#{...}, ...)
</insert>
Reference
  • [https://mybatis.org/mybatis-3/]
  • [https://deeplify.dev/back-end/spring/select-key]

Mapper XML

Result Maps

  • constructor - ์ธ์Šคํ„ด์Šคํ™”๋˜๋Š” ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— ๊ฒฐ๊ณผ๋ฅผ ์‚ฝ์ž…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋จ
    • idArg - ID ์ธ์ž. ์ „๋ฐ˜์ ์œผ๋กœ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ
    • arg - ์ƒ์„ฑ์ž์— ์‚ฝ์ž…๋˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฒฐ๊ณผ
  • id โ€“ ID ๊ฒฐ๊ณผ. ์ „๋ฐ˜์ ์œผ๋กœ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ
<id property="id" column="์ปฌ๋Ÿผ๋ช…"/>
  • result โ€“ ํ•„๋“œ๋‚˜ ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ์— ์‚ฝ์ž…๋˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฒฐ๊ณผ
<result property="ํ•„๋“œ๋ช…" column="์ปฌ๋Ÿผ๋ช…"/>
  • association โ€“ ๋ณต์žกํ•œ ํƒ€์ž…์˜ ์—ฐ๊ด€๊ด€๊ณ„. ๋งŽ์€ ๊ฒฐ๊ณผ๋Š” ํƒ€์ž…์œผ๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค.
  • ์ค‘์ฒฉ๋œ ๊ฒฐ๊ณผ ๋งคํ•‘ โ€“ resultMap ์Šค์Šค๋กœ์˜ ์—ฐ๊ด€๊ด€๊ณ„
  • collection โ€“ ๋ณต์žกํ•œ ํƒ€์ž…์˜ ์ปฌ๋ ‰์…˜
  • ์ค‘์ฒฉ๋œ ๊ฒฐ๊ณผ ๋งคํ•‘ โ€“ resultMap ์Šค์Šค๋กœ์˜ ์—ฐ๊ด€๊ด€๊ณ„
  • discriminator โ€“ ์‚ฌ์šฉํ•  resultMap ์„ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ์‚ฌ์šฉ
    • case โ€“ ๋ช‡๊ฐ€์ง€ ๊ฐ’์— ๊ธฐ์ดˆํ•œ ๊ฒฐ๊ณผ ๋งคํ•‘

association

association ์—˜๋ฆฌ๋จผํŠธ๋Š” โ€œhas-oneโ€ํƒ€์ž…์˜ ๊ด€๊ณ„๋ฅผ ๋‹ค๋ฃฌ๋‹ค.

๋งˆ์ด๋ฐ”ํ‹ฐ์Šค๋Š” ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•˜๋Š” ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

  • ๋‚ดํฌ๋œ(Nested) Select: ๋ณต์žกํ•œ ํƒ€์ž…์„ ๋ฆฌํ„ดํ•˜๋Š” ๋‹ค๋ฅธ ๋งคํ•‘๋œ SQL ๊ตฌ๋ฌธ์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•.
  • ๋‚ดํฌ๋œ(Nested) Results: ์กฐ์ธ๋œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ดํฌ๋œ ๊ฒฐ๊ณผ ๋งคํ•‘์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•.

์—ฐ๊ด€(Association)์„ ์œ„ํ•œ ์ค‘์ฒฉ๋œ Select

<resultMap id="blogResult" type="Blog">
  <association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id="selectAuthor" resultType="Author">
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>

์œ„ ๋ฐฉ๋ฒ•์€ โ€œN+1 Selects ๋ฌธ์ œโ€ ์œผ๋กœ ์•Œ๋ ค์ง„ ๋ฌธ์ œ์ ์„ ๊ฐ€์ง„๋‹ค. N+1 ์กฐํšŒ ๋ฌธ์ œ๋Š” ์ฒ˜๋ฆฌ๊ณผ์ •์˜ ํŠน์ด์„ฑ์œผ๋กœ ์ธํ•ด ์•ผ๊ธฐ๋œ๋‹ค.

  • ๋ ˆ์ฝ”๋“œ์˜ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜์˜ SQL ๊ตฌ๋ฌธ์„ ์‹คํ–‰ํ•œ๋‹ค. (โ€œ+1โ€ ์— ํ•ด๋‹น).
  • ๋ฆฌํ„ด๋œ ๋ ˆ์ฝ”๋“œ๋ณ„๋กœ ๊ฐ๊ฐ์˜ ์ƒ์„ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด select ๊ตฌ๋ฌธ์„ ์‹คํ–‰ํ•œ๋‹ค. (โ€œNโ€ ์— ํ•ด๋‹น). ์ด ๋ฌธ์ œ๋Š” ์ˆ˜๋ฐฑ ๋˜๋Š” ์ˆ˜์ฒœ์˜ SQL ๊ตฌ๋ฌธ ์‹คํ–‰์ด๋ผ๋Š” ๊ฒฐ๊ณผ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ชฉ๋ก์„ ๋กœ๋“œํ•˜๊ณ  ๋‚ดํฌ๋œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด ์ฆ‰์‹œ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค๋ฉด ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ณ  ๊ฒŒ๋‹ค๊ฐ€ ์„ฑ๋Šฅ์€ ๋งŽ์ด ๋‚˜๋น ์งˆ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

๊ด€๊ณ„๋ฅผ ์œ„ํ•œ ๋‚ดํฌ๋œ ๊ฒฐ๊ณผ(Nested Results)

๊ฐœ๋ณ„๊ตฌ๋ฌธ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ ๋Œ€์‹ ์— ํ…Œ์ด๋ธ”์„ ํ•จ๊ป˜ ์กฐ์ธ

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <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"/>
  </association>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  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
  from Blog B left outer join Author A on B.author_id = A.id
  where B.id = #{id}
</select>
  • id ์—˜๋ฆฌ๋จผํŠธ๋Š” ๋‚ดํฌ๋œ ๊ฒฐ๊ณผ ๋งคํ•‘์—์„œ ๋งค์šฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค. ๊ฒฐ๊ณผ ์ค‘ ์œ ์ผํ•œ ๊ฒƒ์„ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•œ ํ•œ๊ฐœ ์ด์ƒ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ช…์‹œํ•ด์•ผ๋งŒ ํ•œ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ๊ฒฐ๊ณผ ์ค‘ ์œ ์ผํ•œ ๊ฒƒ์„ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ๋“ค์„ ์„ ํƒํ•˜๋ผ. ๊ธฐ๋ณธํ‚ค๊ฐ€ ๊ฐ€์žฅ ์ข‹์€ ์„ ํƒ์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

resultMap ์žฌ์‚ฌ์šฉํ•˜๊ธฐ

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <association property="author"
    resultMap="authorResult" />
  <association property="coAuthor"
    resultMap="authorResult"
    columnPrefix="co_" />       <!--๊ฒฐ๊ณผ๋งคํ•‘์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด columnPrefix๋ฅผ ๋ช…์‹œ-->
</resultMap>

<resultMap id="authorResult" type="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"/>
</resultMap>

collection

โ€œhas manyโ€ํƒ€์ž…์˜ ๊ด€๊ณ„๋ฅผ ๋‹ค๋ฃฌ๋‹ค.

<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>

batch insert

  • insert statement
<insert id="insertName">
insert into table (col1) values (#{value})
</insert>
  • execute a batch in java code
List<String> names = new ArrayList<String>();
names.add("Fred");
names.add("Barney");

SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);

try{
  NameMapper mapper = sqlSession.getMapper(NameMapper.class);
  for(String name : names)
    mapper.insertName(name);
  sqlSession.commit();
}finally{
  sqlSession.close();
}
Reference
โš ๏ธ **GitHub.com Fallback** โš ๏ธ