Search
Duplicate

๋™์ ์ฟผ๋ฆฌ

๋™์  ์ฟผ๋ฆฌ

MyBatis๋Š” ๋™์  ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ํƒœ๊ทธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์กฐ๊ฑด์— ๋”ฐ๋ผ SQL ์ฟผ๋ฆฌ๋ฅผ ๋™์ ์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๋™์  ์ฟผ๋ฆฌ ํƒœ๊ทธ

ํƒœ๊ทธ
์„ค๋ช…
<if>
์กฐ๊ฑด์ด ์ฐธ์ผ ๋•Œ๋งŒ SQL ๊ตฌ๋ฌธ ํฌํ•จ
<choose>
Java์˜ switch ๋ฌธ๊ณผ ์œ ์‚ฌ (when, otherwise์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ)
<when>
choose ๋‚ด์—์„œ ์กฐ๊ฑด ๋ถ„๊ธฐ
<otherwise>
choose ๋‚ด์—์„œ ๋ชจ๋“  when ์กฐ๊ฑด์ด ๊ฑฐ์ง“์ผ ๋•Œ ์‹คํ–‰
<where>
WHERE ์ ˆ์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๋ถˆํ•„์š”ํ•œ AND/OR ์ œ๊ฑฐ
<set>
UPDATE์˜ SET ์ ˆ์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๋ถˆํ•„์š”ํ•œ ์‰ผํ‘œ ์ œ๊ฑฐ
<trim>
์ ‘๋‘์‚ฌ/์ ‘๋ฏธ์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐ
<foreach>
์ปฌ๋ ‰์…˜์„ ์ˆœํšŒํ•˜๋ฉฐ SQL ๊ตฌ๋ฌธ ๋ฐ˜๋ณต

<if> ํƒœ๊ทธ

์กฐ๊ฑด์ด ์ฐธ์ผ ๋•Œ๋งŒ SQL ๊ตฌ๋ฌธ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
<select id="select" resultType="User"> SELECT * FROM users <where> <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select>
XML
๋ณต์‚ฌ

<choose>, <when>, <otherwise> ํƒœ๊ทธ

์—ฌ๋Ÿฌ ์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜๋งŒ ์„ ํƒํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
<select id="select" resultType="User"> SELECT * FROM users <where> <choose> <when test="name != null"> AND name = #{name} </when> <when test="email != null"> AND email = #{email} </when> <otherwise> AND status = 'ACTIVE' </otherwise> </choose> </where> </select>
XML
๋ณต์‚ฌ

<where> ํƒœ๊ทธ

WHERE ์ ˆ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ , ์ฒซ ๋ฒˆ์งธ AND/OR๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
<select id="select" resultType="User"> SELECT * FROM users <where> <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select>
XML
๋ณต์‚ฌ

<set> ํƒœ๊ทธ

UPDATE์˜ SET ์ ˆ์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ , ๋งˆ์ง€๋ง‰ ์‰ผํ‘œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
<update id="update"> UPDATE users <set> <if test="name != null"> name = #{name}, </if> <if test="age != null"> age = #{age}, </if> </set> WHERE id = #{id} </update>
XML
๋ณต์‚ฌ

<trim> ํƒœ๊ทธ

์ ‘๋‘์‚ฌ๋‚˜ ์ ‘๋ฏธ์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
<select id="findUsers" resultType="User"> SELECT * FROM users <trim prefix="WHERE" prefixOverrides="AND |OR "> <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </trim> </select>
XML
๋ณต์‚ฌ

<trim> ํƒœ๊ทธ ์†์„ฑ

์†์„ฑ
์„ค๋ช…
prefix
์ƒ์„ฑ๋œ SQL ์•ž์— ์ถ”๊ฐ€ํ•  ์ ‘๋‘์‚ฌ
suffix
์ƒ์„ฑ๋œ SQL ๋’ค์— ์ถ”๊ฐ€ํ•  ์ ‘๋ฏธ์‚ฌ
prefixOverrides
์ƒ์„ฑ๋œ SQL ์•ž์—์„œ ์ œ๊ฑฐํ•  ๋ฌธ์ž์—ด (๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„)
suffixOverrides
์ƒ์„ฑ๋œ SQL ๋’ค์—์„œ ์ œ๊ฑฐํ•  ๋ฌธ์ž์—ด (๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„)

<trim> ํƒœ๊ทธ ๋™์ž‘ ์„ค๋ช…

<trim> ํƒœ๊ทธ๋Š” ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” SQL ๊ตฌ๋ฌธ์˜ ์•ž๋’ค์— ํŠน์ • ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์œ„ ์˜ˆ์ œ ๋ถ„์„:
โ€ข
prefix="WHERE": trim ๋ธ”๋ก ๋‚ด์šฉ์ด ์žˆ์œผ๋ฉด ์•ž์— "WHERE"๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
prefixOverrides="AND |OR ": ์ƒ์„ฑ๋œ SQL์˜ ๋งจ ์•ž์— "AND " ๋˜๋Š” "OR "๊ฐ€ ์žˆ์œผ๋ฉด ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
โ€ข
๋งŒ์•ฝ name๊ณผ age๊ฐ€ ๋ชจ๋‘ null์ด ์•„๋‹ˆ๋ผ๋ฉด, ์ตœ์ข… SQL์€ SELECT * FROM users WHERE name = ? AND age = ?๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
โ€ข
์ฒซ ๋ฒˆ์งธ ์กฐ๊ฑด์˜ "AND"๊ฐ€ prefixOverrides์— ์˜ํ•ด ์ œ๊ฑฐ๋˜์–ด ์˜ฌ๋ฐ”๋ฅธ SQL์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
์ถ”๊ฐ€ ์˜ˆ์ œ - suffixOverrides ์‚ฌ์šฉ:
<update id="updateUser"> UPDATE users <trim prefix="SET" suffixOverrides=","> <if test="name != null"> name = #{name}, </if> <if test="age != null"> age = #{age}, </if> </trim> WHERE id = #{id} </update>
XML
๋ณต์‚ฌ
์ด ์˜ˆ์ œ์—์„œ๋Š” ๋งˆ์ง€๋ง‰ ์‰ผํ‘œ๊ฐ€ ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. <set> ํƒœ๊ทธ์™€ ๋™์ผํ•œ ํšจ๊ณผ๋ฅผ ๋ƒ…๋‹ˆ๋‹ค.

<foreach> ํƒœ๊ทธ

์ปฌ๋ ‰์…˜์„ ์ˆœํšŒํ•˜๋ฉฐ SQL ๊ตฌ๋ฌธ์„ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค. IN ์ ˆ์„ ์ƒ์„ฑํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
<select id="findUsersByIds" resultType="User"> SELECT * FROM users WHERE id IN <foreach item="id" collection="list" open="(" separator="," close=")"> #{id} </foreach> </select>
XML
๋ณต์‚ฌ

<foreach> ํƒœ๊ทธ ์†์„ฑ

์†์„ฑ
์„ค๋ช…
collection
๋ฐ˜๋ณตํ•  ์ปฌ๋ ‰์…˜ (list, array, map ๋“ฑ)
item
ํ˜„์žฌ ๋ฐ˜๋ณต ํ•ญ๋ชฉ์„ ์ฐธ์กฐํ•  ๋ณ€์ˆ˜๋ช…
index
ํ˜„์žฌ ๋ฐ˜๋ณต์˜ ์ธ๋ฑ์Šค๋ฅผ ์ฐธ์กฐํ•  ๋ณ€์ˆ˜๋ช…
open
๋ฐ˜๋ณต ์‹œ์ž‘ ์‹œ ์ถ”๊ฐ€ํ•  ๋ฌธ์ž์—ด
close
๋ฐ˜๋ณต ์ข…๋ฃŒ ์‹œ ์ถ”๊ฐ€ํ•  ๋ฌธ์ž์—ด
separator
๊ฐ ํ•ญ๋ชฉ ์‚ฌ์ด์— ์ถ”๊ฐ€ํ•  ๊ตฌ๋ถ„์ž

<bind> ํƒœ๊ทธ

OGNL ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. LIKE ๊ฒ€์ƒ‰ ์‹œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
<select id="findUsersByName" resultType="User"> <bind name="pattern" value="'%' + name + '%'" /> SELECT * FROM users WHERE name LIKE #{pattern} </select>
XML
๋ณต์‚ฌ

<bind> ํƒœ๊ทธ ๋™์ž‘ ์„ค๋ช…

<bind> ํƒœ๊ทธ๋Š” OGNL(Object-Graph Navigation Language) ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์œ„ ์˜ˆ์ œ ๋ถ„์„:
โ€ข
name="pattern": ์ƒ์„ฑํ•  ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
value="'%' + name + '%'": OGNL ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์ž…๋ ฅ๋ฐ›์€ name ๊ฐ’ ์•ž๋’ค์— %๋ฅผ ๋ถ™์ž…๋‹ˆ๋‹ค.
โ€ข
๋งŒ์•ฝ name์ด "ํ™๊ธธ๋™"์ด๋ผ๋ฉด, pattern ๋ณ€์ˆ˜๋Š” "%ํ™๊ธธ๋™%"์ด ๋ฉ๋‹ˆ๋‹ค.
โ€ข
์ƒ์„ฑ๋œ pattern ๋ณ€์ˆ˜๋Š” #{pattern}์œผ๋กœ SQL ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<bind> ํƒœ๊ทธ์˜ ์žฅ์ :
โ€ข
SQL ์ฟผ๋ฆฌ๋ฅผ ๋” ๊น”๋”ํ•˜๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
๋ณต์žกํ•œ ๋ฌธ์ž์—ด ์กฐ์ž‘์„ SQL ์™ธ๋ถ€์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ฟผ๋ฆฌ ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ถ”๊ฐ€ ์˜ˆ์ œ - ๋‚ ์งœ ํ˜•์‹ ๋ณ€ํ™˜:
<select id="findUsersByDate" resultType="User"> <bind name="startDate" value="startDate + ' 00:00:00'" /> <bind name="endDate" value="endDate + ' 23:59:59'" /> SELECT * FROM users WHERE created_at BETWEEN #{startDate} AND #{endDate} </select>
XML
๋ณต์‚ฌ
์ด ์˜ˆ์ œ์—์„œ๋Š” ๋‚ ์งœ ๋ฌธ์ž์—ด์— ์‹œ๊ฐ„์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฒ”์œ„ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

OGNL(Object-Graph Navigation Language) ํ‘œํ˜„์‹์ด๋ž€?

OGNL์€ Java ๊ฐ์ฒด์˜ ์†์„ฑ์„ ํƒ์ƒ‰ํ•˜๊ณ  ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ํ‘œํ˜„ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. MyBatis์—์„œ๋Š” ๋™์  SQL์„ ์ž‘์„ฑํ•  ๋•Œ OGNL์„ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์ฐธ์กฐํ•˜๊ณ  ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

OGNL์˜ ์ฃผ์š” ๊ธฐ๋Šฅ

โ€ข
์†์„ฑ ์ ‘๊ทผ: ๊ฐ์ฒด์˜ ์†์„ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: user.name, user.address.city
โ€ข
๋ฉ”์„œ๋“œ ํ˜ธ์ถœ: ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: name.length(), name.toUpperCase()
โ€ข
์—ฐ์‚ฐ: ์‚ฐ์ˆ , ๋…ผ๋ฆฌ, ๋น„๊ต ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: age + 1, age > 18
โ€ข
๋ฌธ์ž์—ด ์กฐ์ž‘: ๋ฌธ์ž์—ด์„ ๊ฒฐํ•ฉํ•˜๊ฑฐ๋‚˜ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: '%' + name + '%'
โ€ข
์ปฌ๋ ‰์…˜ ์ ‘๊ทผ: ๋ฆฌ์ŠคํŠธ๋‚˜ ๋ฐฐ์—ด์˜ ์š”์†Œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: list[0], map['key']

MyBatis์—์„œ OGNL ์‚ฌ์šฉ ์˜ˆ์ œ

1. ์กฐ๊ฑด ์ฒดํฌ:
<if test="name != null and name != ''"> AND name = #{name} </if>
XML
๋ณต์‚ฌ
2. ์ปฌ๋ ‰์…˜ ์ฒดํฌ:
<if test="list != null and list.size() > 0"> AND id IN <foreach item="id" collection="list" open="(" separator="," close=")"> #{id} </foreach> </if>
XML
๋ณต์‚ฌ
3. ๋ฌธ์ž์—ด ์กฐ์ž‘:
<bind name="pattern" value="'%' + keyword + '%'" /> SELECT * FROM users WHERE name LIKE #{pattern}
XML
๋ณต์‚ฌ
4. ๋ณต์žกํ•œ ์กฐ๊ฑด:
<if test="age != null and (age >= 18 and age <= 65)"> AND age BETWEEN 18 AND 65 </if>
XML
๋ณต์‚ฌ

OGNL ์ฃผ์š” ์—ฐ์‚ฐ์ž

์—ฐ์‚ฐ์ž
์„ค๋ช…
์˜ˆ์ œ
.
์†์„ฑ ์ ‘๊ทผ
user.name
==, !=
๋™๋“ฑ ๋น„๊ต
name == 'admin'
>, <, >=, <=
ํฌ๊ธฐ ๋น„๊ต
age > 18
and, or, not
๋…ผ๋ฆฌ ์—ฐ์‚ฐ
name != null and age > 18
+, -, *, /, %
์‚ฐ์ˆ  ์—ฐ์‚ฐ
price * quantity
[]
์ปฌ๋ ‰์…˜ ์ ‘๊ทผ
list[0],map['key']

์ฃผ์˜์‚ฌํ•ญ

โ€ข
XML์—์„œ๋Š” <์™€ >๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ &amp;lt;์™€ &amp;gt;๋กœ ํ‘œํ˜„ํ•˜๊ฑฐ๋‚˜, <![CDATA[]]>๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
null ์ฒดํฌ๋ฅผ ํ•  ๋•Œ๋Š” != null์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
โ€ข
๋ฌธ์ž์—ด ๋น„๊ต ์‹œ ์ž‘์€๋”ฐ์˜ดํ‘œ('')๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.