๐Ÿ’พ DB_

[Spring Boot + MyBatis] SqlSessionFactory ์˜ค๋ฅ˜๋ถ€ํ„ฐ resultMap ์ ์šฉ๊นŒ์ง€

CodeLoge 2025. 5. 9. 19:42

1. ๊ฐœ์š”

Spring Boot์™€ MyBatis๋ฅผ ์—ฐ๋™ํ•  ๋•Œ ๊ฐ€์žฅ ํ”ํžˆ ๋งˆ์ฃผ์น˜๋Š” ์„ค์ • ์˜ค๋ฅ˜ ์ค‘ ํ•˜๋‚˜์ธ SqlSessionFactory ์ƒ์„ฑ ์‹คํŒจ ์ด์Šˆ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋Š”์ง€,

๊ทธ๋ฆฌ๊ณ  resultMap์„ ์–ธ์ œ ๊ผญ ์จ์•ผ ํ•˜๋Š”์ง€๋„ ์‹ค์ œ ์‚ฌ๋ก€ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •๋ฆฌ

 

2. ๋ฌธ์ œ ๋ฐœ์ƒ : SqlSessionFactory ์ดˆ๊ธฐํ™” ์‹คํŒจ

โŒ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€


Failed to parse config resource: class path resource [sql-map-config.xml]

๐Ÿ” ์›์ธ ๋ถ„์„

• sql-map-config.xml ํŒŒ์ผ์ด ์‹ค์ œ๋กœ ์กด์žฌํ•˜์ง€ ์•Š๊ฑฐ๋‚˜,

 application.yml์—์„œ ์ž˜๋ชป๋œ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ–ˆ๊ฑฐ๋‚˜,

 ํ˜น์€ xml ๋‚ด๋ถ€ ๋ฌธ๋ฒ• ์˜ค๋ฅ˜ (์˜ˆ: ํƒœ๊ทธ ๋ˆ„๋ฝ, ์˜คํƒ€ ๋“ฑ)

 

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

 sql-map-config.xml์ด ์ •๋ง ์กด์žฌํ•˜๋Š”์ง€ resources/ ํ•˜์œ„ ํ™•์ธ

 ๋ฌธ๋ฒ• ์˜ค๋ฅ˜๊ฐ€ ์—†๋Š”์ง€ IDE์—์„œ ํ™•์ธ (<configuration>, <mappers> ๋“ฑ)

 ๊ตณ์ด ์„ค์ • ํŒŒ์ผ์ด ํ•„์š” ์—†๋‹ค๋ฉด application.yml์—์„œ ์„ค์ • ์ œ๊ฑฐ


# ํ•„์š” ์—†์œผ๋ฉด ์ด๊ฑฐ ์ œ๊ฑฐ
mybatis:
  config-location: classpath:sql-map-config.xml

โœ… ๋ณธ ํ”„๋กœ์ ํŠธ ์˜ค๋ฅ˜ ์›์ธ


→ .xml ์—์„œ ์„ค์ •ํ•œ resource = ".xmlํŒŒ์ผ" ์˜ ์ด๋ฆ„๊ณผ ์‹ค์ œ ์ €์žฅ๋œ ํŒŒ์ผ์˜ ์ด๋ฆ„์ด ๋‹ค๋ฆ„ (์‹ค์ œ ํŒŒ์ผ์€ _๋ฅผ ์‚ฌ์šฉ .xml์—์„œ๋Š” - ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ์„ ์ฐพ์ง€ ๋ชปํ•จ


3. resultType๋งŒ์œผ๋กœ ์ถฉ๋ถ„ํ•œ๊ฐ€? resultMap ๊ผญ ์จ์•ผ ํ•˜๋‚˜?

๐Ÿค” ์˜๋ฌธ

Spring Boot + MyBatis์—์„œ resultType์œผ๋กœ๋„ ์ž๋™ ๋งคํ•‘์ด ๋˜๋Š”๋ฐ ๊ตณ์ด resultMap์„ ์จ์•ผ ํ•˜๋‚˜?

 

โœ… ๊ฒฐ๋ก 

 

์ปฌ๋Ÿผ๋ช…๊ณผ VO ํ•„๋“œ๋ช…์ด ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋ฉด resultType๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„

๋‹ค๋งŒ ์•„๋ž˜ ์กฐ๊ฑด์—์„  resultMap์ด ํ•„์š”

 

4. resultMap์ด ๊ผญ ํ•„์š”ํ•œ ์ƒํ™ฉ

โœ” ๊ณ„์‚ฐ ์ปฌ๋Ÿผ์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ (VO์—๋งŒ ์žˆ๊ณ  DB์—๋Š” ์—†๋Š” ํ•„๋“œ)


SELECT MEMBER_ID, (SELECT COUNT(*) FROM PURCHASE WHERE MEMBER_ID = M.MEMBER_ID) AS PURCHASE_COUNT
FROM MEMBER M

→ PURCHASE_COUNT๋Š” DB ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ์ด ์•„๋‹ˆ๋ผ์„œ, VO์—๋งŒ ์žˆ๋Š” purchaseCount์™€ ์ž๋™ ๋งคํ•‘๋˜์ง€ ์•Š์Œ


โœ” ์กฐ์ธ ๊ฒฐ๊ณผ๊ฐ€ ํฌํ•จ๋  ๋•Œ


SELECT REVIEW.*, MEMBER.MEMBER_NAME, MEMBER.IS_WITHDRAW
FROM REVIEW JOIN MEMBER ON REVIEW.MEMBER_ID = MEMBER.MEMBER_ID

→ memberNamememberIsWithdraw ๋“ฑ์€ JOIN์œผ๋กœ ๊ฐ€์ ธ์˜จ ์™ธ๋ถ€ ์ปฌ๋Ÿผ์ด๋ผ resultMap ํ•„์ˆ˜


5. ์˜ˆ์‹œ ์ฝ”๋“œ

โœ… resultType์œผ๋กœ ์ถฉ๋ถ„ํ•œ ๊ฒฝ์šฐ


<select id="SELECTALL" resultType="member">
  SELECT MEMBER_NUMBER, MEMBER_ID, MEMBER_NAME FROM MEMBER
</select>

โœ… resultMap์„ ๋ฐ˜๋“œ์‹œ ์จ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ


<resultMap id="memberMap" type="MemberVO">
  <id property="memberNumber" column="MEMBER_NUMBER"/>
  <result property="memberId" column="MEMBER_ID"/>
  <result property="purchaseCount" column="PURCHASE_COUNT"/>
</resultMap>

<select id="SELECTWITHCOUNT" resultMap="memberMap">
  SELECT M.MEMBER_NUMBER, M.MEMBER_ID,
         (SELECT COUNT(*) FROM PURCHASE WHERE MEMBER_NUMBER = M.MEMBER_NUMBER) AS PURCHASE_COUNT
  FROM MEMBER M
</select>

โœ… ๋ณธ ํ”„๋กœ์ ํŠธ ์˜ค๋ฅ˜ ์›์ธ


→ ์˜ค๋ผํด 11g ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•œ ๋ณ„์นญ ๊ธธ์ด ์ œํ•œ์œผ๋กœ ์ธํ•ด,

๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ์ปฌ๋Ÿผ๋ช… PRODUCT_COMBO_DISCOUNTED_PRICE์—์„œ COMBO_DISCOUNTED_PRICE๋กœ ๋ณ€๊ฒฝํ•จ

→ MyBatis๊ฐ€ ์ž๋™ ๋งคํ•‘์— ์‹คํŒจํ•˜์—ฌ ํ–‰(row) ์ž์ฒด๋ฅผ null๋กœ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ null๋กœ ๋ฐ˜ํ™˜

→ List ์ž์ฒด๊ฐ€ null์ด์–ด์„œ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ์‹คํŒจ

→ resultMap์„ ์‚ฌ์šฉํ•˜์—ฌ property = "VO์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉค๋ฒ„๋ณ€์ˆ˜" / column = "SQL๋ฌธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปฌ๋Ÿผ๋ช…"์„ 1:1๋กœ ๋งคํ•‘ํ•ด์ฃผ์–ด ๋ฐ์ดํ„ฐ ์ถ”์ถœ 


6. ๋งˆ๋ฌด๋ฆฌ

์ด๋ฒˆ ์‹ค์ „ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…์„ ํ†ตํ•ด,

 MyBatis ์„ค์ • ์—๋Ÿฌ(SqlSessionFactory)์˜ ์›์ธ๊ณผ ๋Œ€์ฒ˜๋ฒ•

 resultType๊ณผ resultMap์˜ ์ ์šฉ ๊ธฐ์ค€์„ ๋ช…ํ™•ํžˆ ์ •๋ฆฌ ๊ฐ€๋Šฅ