Skip to content
/ JPA Public

๐Ÿ‘ปJPA ๊ฐœ๋… ์ •๋ฆฌ & ํ”„๋กœ์ ํŠธ๐Ÿ‘ป

Notifications You must be signed in to change notification settings

hyunbin1/JPA

Repository files navigation

JPA

SQL ์ค‘์‹ฌ์ ์ธ ๊ฐœ๋ฐœ์˜ ๋ฌธ์ œ์ 

ํ•œ๋ฒˆ ์šฐ๋ฆฌ๊ฐ€ ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํ„ฐ์— ์ €์žฅ์„ ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž. ์šฐ๋ฆฌ๋Š” ๊ด€๊ณ„ํ˜• DB, NoSQL, ํŒŒ์ผ ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•์‹์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ๋ณด๊ด€ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ€์žฅ ํ˜„์‹ค์ ์ด๊ณ  ํ˜„๋ช…ํ•œ ๋ฐฉ๋ฒ•์€ ๊ด€๊ณ„ํ˜• DB์ด๋‹ค. No SQL๋„ ๋ฐฉ๋ฒ•์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ์•„์ง๊นŒ์ง€๋Š” ์ฃผ ๋ฉ”์ธ์œผ๋กœ ๋‘์ง€๋Š” ์•Š๋Š”๋‹ค.

์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•ด๋ณธ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ์šฐ์„  ํ๋ฆ„์€ '1. ๊ฐ์ฒด๋ฅผ SQL๋ฌธ์œผ๋กœ ๋ณ€ํ™˜ -> 2. SQL์„ RDB(๊ด€๊ณ„ํ˜• DB)์— ์ €์žฅ' ์ˆœ์ด๋‹ค. ์ด๋ฅผ ๊ฐ์ฒด๋ฅผ SQL๋กœ ๋งคํ•‘ํ•œ๋‹ค๊ณ  ๋งํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋งคํ•‘ ๊ณผ์ •์€ ๋งค์šฐ ๋ฐฉ๋ณต์ ์ธ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋กœ์ง์„ ์งค ์‹œ๊ฐ„์— ๋งคํ•‘์„ ํ•˜๋ฉฐ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ•˜๋Š” ๋ฌธ์ œ์ ์ด ์ƒ๊ธด๋‹ค.

์ฒซ ๋ฒˆ์งธ ์ด์œ : ๋ฌดํ•œ ๋ฐ˜๋ณต๊ณผ ์ง€๋ฃจํ•œ ์ฝ”๋“œ - Java ๊ฐ์ฒด์™€ sql ์„œ๋กœ ์ „ํ™˜ ํ•˜๊ธฐ, CRUD์งœ๊ธฐ ๋“ฑ ๋งค์šฐ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์ผ์ผํžˆ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค. ๋˜ํ•œ ์ˆ˜์ •ํ•˜๊ธฐ๋„ ๋งค์šฐ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์ด๋Ÿฌ๋‹ค ๋ณด๋ฉด ์ฝ”๋“œ๋ฅผ ๋นผ๋†“๋Š” ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ์‹ค์ˆ˜๊ฐ€ ์ƒ๊ธด๋‹ค.

๋‘ ๋ฒˆ์งธ ์ด์œ : ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ๋ถˆ์ผ์น˜. - ๊ฐ์ฒด๊ฐ€ ๋‚˜์˜จ ์‚ฌ์ƒ๊ณผ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๊ฐ€ ๋‚˜์˜จ ์ด์œ (์‚ฌ์ƒ)์ด ๋‹ค๋ฅด๋‹ค. ๊ด€๊ณ„ํ˜• DB๋Š” ์ •๊ตํ™”ํ•ด์„œ ๋ณด๊ด€์„ ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉ์ ์ด์ง€๋งŒ, ๊ฐ์ฒด๋Š” ํ•„๋“œ์™€ ๋ฉ”์„œ๋“œ๋ฅผ ์ž˜ ์บก์Šํ™”ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฌธ์ œ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฅผ ์„œ๋กœ ์œตํ•ฉํ•˜๋ ค๋‹ค๋ณด๋‹ˆ ํŒจ๋Ÿฌ๋‹ค์ž„์ด ์ผ์น˜ํ•˜์ง€ ์•Š์•„ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค. ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์žˆ์„๊นŒ?

๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ฐจ์ด:

  1. ์ƒ์†: ๊ฐ์ฒด์—๋Š” ์ƒ์† ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ DB๋Š” ์ƒ์† ๊ด€๊ณ„์™€ ์œ ์‚ฌํ•œ ๊ฐœ๋…์ด ์žˆ์ง€๋งŒ ์—„์—ฐํžˆ ๋‹ค๋ฅธ ๊ฐœ๋…์ด๊ธฐ ๋•Œ๋ฌธ์— ์—†๋‹ค๊ณ  ๋ณด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

    ์ด๋ ‡๊ฒŒ ์ƒ์† ๊ฐœ๋… ๊ฐ„์˜ ์ฐจ์ด์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๊ฐ์ฒด๋ฅผ DB์— ๋ฐ€์–ด ๋„ฃ์œผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ๋ ๊นŒ? ๋Œ€๋ถ€๋ถ„ ์ด๋ฅผ ํฌ๊ธฐํ•ด๋ฒ„๋ฆฐ๋‹ค. DB์—์„œ ๊ฐ์ฒด์˜ ์ƒ์† ๊ด€๊ณ„์™€ ๊ฐ€์žฅ ์œ ์‚ฌํ•œ ๋ฐฉ๋ฒ•์€ Table ์Šˆํผํƒ€์ž… ์„œ๋ธŒํƒ€์ž… ๊ด€๊ณ„์ด๋‹ค.

    ์˜ˆ๋ฅผ ํ•œ๋ฒˆ ๋“ค์–ด๋ณด์ž. ์šฐ๋ฆฌ๋Š” ์‡ผํ•‘๋ชฐ์„ ์šด์˜ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด Java์˜ ๊ฐ์ฒด๋กœ ๊ตฌ์กฐ๋ฅผ ์งค ๋–„, ์šฐ๋ฆฌ๋Š” 'Item(์ƒํ’ˆ)-id, ์ด๋ฆ„, ๊ฐ€๊ฒฉ'์ด๋ผ๋Š” ๋ถ€๋ชจ ํด๋ ˆ์Šค๋ฅผ ๋งŒ๋“  ํ›„, ์ด๋ฅผ ์ƒ์†๋ฐ›์•„ 'Album-์ž‘๊ณก๊ฐ€', 'Movie-๊ฐ๋…, ๋ฐฐ'์šฐ,' Book-์ž‘๊ฐ€, ISBN' ๋“ฑ ์„œ๋ธŒ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ DB๋กœ ๋ชจ๋ธ๋งํ•ด๋ณด์ž. ๋ชจ๋ธ๋ง์„ ํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

    1. ๋ฐ˜๋ณต ๋ฌธ์ œ: Item ID๋ฅผ ๋ชจ๋“  ํ…Œ์ด๋ธ”๋งˆ๋‹ค ์‚ฝ์ž…ํ•ด์•ผํ•˜๋Š” ๋ฐ˜๋ณต ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค.
    2. ์กฐํšŒ ๋ฌธ์ œ: DB์—์„œ๋Š” ๊ฐ๊ฐ์˜ ํ…Œ์ด๋ธ”์— ๋”ฐ๋ฅธ JOIN SQL์„ ์ž‘์„ฑํ•ด์•ผํ•˜๊ณ , ๊ฐ๊ฐ์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ž๋ฐ”๋Š” get๋งŒ ์‚ฌ์šฉํ•ด์„œ ์†์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

โ€‹ => ์ฆ‰ RDB์— ๋„ฃ๋Š” ์ˆœ๊ฐ„ SQL๋งคํ•‘ ์ž‘์—…์ด ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์—, DB์— ์ €์žฅํ•  ๊ฐ์ฒด๋Š” ์ƒ์† ๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

  1. ์—ฐ๊ด€๊ด€๊ณ„: ๊ฐ์ฒด๋Š” ์ฐธ์กฐ(๋ ˆํผ๋Ÿฐ์Šค)๊ฐ’์„ ๊ฐ€์ง€๊ณ  ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ฆ‰ ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด memer.getTeam() ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ ์กฐํšŒ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ DB๋Š” ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ FK๋ฅผ Join์„ ํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๋ฌด์—‡์ด ๋ฌธ์ œ์ผ๊นŒ?

    ์ž๋ฐ”์˜ ๊ฐ์ฒด๋Š” ์ผ๋ฐฉํ–ฅ์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Member์—์„œ Team์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, Team์—์„œ๋Š” Member๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์—†๋‹ค. ๋ฐ˜๋ฉด, DB๋Š” ์–‘๋ฐฉํ–ฅ์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ ๊ฐ„์˜ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

    ์ด๋Ÿฌํ•œ ํŠน์ง•์„ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ๊ฐ์ฒด๋ฅผ ๋ชจ๋ธ๋งํ•  ๋•Œ Member์— Team ํ•„๋“œ๋ฅผ ๊ฐ€์ ธ์™€ ์ฐธ์กฐ๋กœ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค. ์ด๋ฅผ INSERT INTO MEMBER์—์„œ TEAM_ID์— ๊ฐ’์„ ๋„ฃ์„ ๋•Œ ์šฐ๋ฆฌ๋Š” ๋˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ•„๋“œ์— ์ €์žฅํ•œ TEAM์˜ ๊ฐ’์€ ์ฐธ์กฐ ๊ฐ’์ด์ง€ DB์˜ PK๊ฐ’์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋Š” member.getTema().getId()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์–ด์ฐŒ์–ด์ฐŒ ํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. '

    // ์‚ฌ์ง„

    ํ•˜์ง€๋งŒ, ์ด๋ฅผ ์กฐํšŒํ•  ๋•Œ๋„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. sql์„ ์‹คํ–‰ํ•œ ํ›„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ™˜ ํšŒ์›, ํŒ€์— ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์ž…๋ ฅํ•œ๋‹ค. ๊ทธ๋‹ค์Œ์— ํšŒ์›๊ณผ ํŒ€ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•ด ์ค€ ํ›„ member๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

    // ์‚ฌ์ง„

    ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ์ฒด์˜ ์ž๋ฐ” ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋งŒ์„ ์‚ฌ์šฉํ•ด๋„ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ฆ‰, ์œ„์™€ ๊ฐ™์ด DB์™€ ์—ฐ๊ด€ ์‹œํ‚ค๋ ค๋Š” ์ˆœ๊ฐ„ ์ปค๋‹ค๋ž€ ๋ฌธ์ œ๋“ค์ด ๋งŽ์ด ๋ฐœ์ƒํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

    ๋” ๋‚˜์•„๊ฐ€, ๊ฐ์ฒด๋Š” ์ž์œ ๋กญ๊ฒŒ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค. member.getTeam()์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ชจ๋‘ ์‰ฝ๊ฒŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์•„๊นŒ ์ „์ œ์—์„œ ์‹คํ–‰ํ•œ SQL์— ๋”ฐ๋ผ์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์—, member.getTeam()์€ ์ž‘๋™ํ•˜์ง€๋งŒ ์•„์ง ๋งคํ•‘ํ•˜์ง€ ์•Š์€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋Š” ์กฐํšŒํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ์‹ ๋ขฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ getTeam() ๋ฉ”์„œ๋“œ๋„ ์žˆ๊ณ , getOrder ๋ฉ”์„œ๋“œ๋„ ์žˆ์ง€๋งŒ, ์ด ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ๋กœ ๋งคํ•‘์ด ๋˜์—ˆ๋Š”์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ๋‹ค ๊นŒ๋ณด์ง€ ์•Š๋Š” ์ด์ƒ ๊ฐ์ฒด(์—”ํ‹ฐํ‹ฐ)์— ๋Œ€ํ•œ ์‹ค๋ขฐํ•  ์ˆ˜ ์—†์–ด ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ๊ฐ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

    **๋”ฐ๋ผ์„œ ๊ณ„์ธตํ˜• ์•„ํ‚คํ…Œ์ฒ˜๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์ง„์ •ํ•œ ์˜๋ฏธ์˜ ๊ณ„์ธต ๋ถ„ํ• ์ด ์–ด๋ ต๋‹ค. ๊ฐ์ฒด๋‹ต๊ฒŒ ๋ชจ๋ธ๋ง ํ• ์ˆ˜๋ก ๋งคํ•‘ ์ž‘์—…๋งŒ ๋Š˜์–ด๋‚˜๋Š ๊ฒƒ์ด๋‹ค. **

JPA๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

๊ทธ๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ž๋ฐ” ์ปฌ๋ ‰์…˜์— ์ €์žฅ ํ•˜๋“ฏ์ด DB์— ์ €์žฅํ•  ์ˆ˜๋Š” ์—†์„๊นŒ? ๋ผ๋Š” ๋ฌผ์Œ์ด ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค.

JPA๋ž€?

JPA๋Š” Java Persistence API์˜ ์ค€๋ง์ด๋‹ค. ์ด๋Š” ์ž๋ฐ” ์ง„์˜์˜ ORM ๊ธฐ์ˆ  ํ‘œ์ค€์ด๋‹ค. ORM์€ Object-relational mapping(๊ฐœ๊ฒŒ ๊ด€๊ณ„ ๋งคํ•‘)์œผ๋กœ ๊ฐ์ฒด๋Š” ๊ฐ์ฒด๋ฐ๋กœ ์„ค๊ณ„๋ฅผ ํ•˜๊ณ , ๊ด€๊ณ„ํ˜• DB๋Š” ๊ด€๊ณ„ํ˜• DB๋Œ€๋กœ ์„ค๊ณ„๋ฅผ ํ•˜๋ฉด ORM ํ”„๋ž˜์ž„์›Œํฌ๊ฐ€ ๊ทธ ์ค‘๊ฐ„์—์„œ ์„œ๋กœ ๊ฐ„์˜ ๋งคํ•‘์„ ํ•ด์ค€๋‹ค. ๋Œ€์ค‘์ ์ธ ์–ธ์–ด์—๋Š” ๋Œ€๋ถ€๋ถ„ ORM๊ธฐ์ˆ ์ด ์กด์žฌํ•œ๋‹ค. TypeScript๋„ TypeORM์œผ๋กœ ์ œ๊ณต์„ ํ•ด์ค€๋‹ค.

JPA๋Š” Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ JDBC API ์‚ฌ์ด์—์„œ ๋™์ž‘์„ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์ž๋Š” JDBC๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์ง€๋Š” ์•Š๊ณ  JPA๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JDBC API์— ์ ‘๊ทผํ•˜์—ฌ DB์™€ ์ƒํ˜ธ์ž‘์šฉ์„ ํ•œ๋‹ค. JDBC API๋Š” SQL๋ฌธ์„ DB์— ์ œ๊ณตํ•˜๊ณ  DB๋Š” ๊ฒฐ๊ณผ๋ฅผ JDBC API์— ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

JPA ๋™์ž‘ ๋ฐฉ์‹

  1. ์ €์žฅ: MemberDAO(java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)์—์„œ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ณ  ์‹ถ์–ด์„œ ๋ฉค๋ฒ„ ๊ฐ์ฒด๋ฅผ ๋„˜๊ธด๋‹ค. ๊ทธ๋Ÿฌ๋ฉด JPA๊ฐ€ Entity๋ฅผ ๋ถ„์„ํ•˜๊ณ , INSERT SQL์„ ์ƒ์„ฑํ•˜์—ฌ JDBC API๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ๊ฒƒ์€ ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ๋ถˆ์ผ์น˜๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค๋Š” ์ ์ด ๊ฐ€์žฅ ํฐ ๋ชฉ์ ์ด์ž ์žฅ์ ์ด๋‹ค.

  2. ์กฐํšŒ: java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ find(id)๋ฅผ ์š”๊ตฌํ•˜๋ฉด JPA๋Š” SELECT SQL๋ฅผ ์ƒ์„ฑํ•˜์—ฌ JDBC API๋ฅผ ํ†ตํ•˜์—ฌ SQL์„ DB์— ๋ณด๋‚ด๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ ResultSet์„ ๋งคํ•‘ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

JPA๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

  1. ์ƒ์‚ฐ์„ฑ: JPA๋กœ CRUD๋ฅผ ํ•˜๋Š” ๊ฒƒ์€ ์ฝ”๋“œ ํ•œ์ค„๋กœ ํ•  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋‹ค.

  2. ์œ ์ง€๋ณด์ˆ˜: ๊ธฐ์กด์˜ ํ•„๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๋ชจ๋“  SQL๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ํ•„๋“œ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด sql์€ jpa๊ฐ€ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

  3. ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ๋ถˆ์ผ์น˜ ํ•ด๊ฒฐ: JPA๊ฐ€ ์ƒ์†์ฒ˜๋ฆฌ๋ฅผ ๊ธฐ๊ฐ€๋ง‰ํžˆ๊ฒŒ ํ•œ๋‹ค. ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ, ๊ณ„์ธต. - ์ž์œ ๋กœ์šด ๊ฐ์ฒด ํƒ์ƒ‰์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค. ๋˜ํ•œ ๋™์ผํ•œ ํŠธ๋žœ์ ์…˜์—์„œ ์กฐํšŒํ•œ ์—”ํ‹ฐํ‹ฐ๋Š” ๊ฐ™์Œ์„ ๋ณด์žฅํ•ด์ค€๋‹ค.

  4. ์„ฑ๋Šฅ: JPA์˜ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค.

    1. 1์ฐจ ๊ฐœ์‹œ์™€ ๋™์ผ์„ฑ ๋ณด์žฅ:

      • ๊ฐ™์€ ํŠธ๋žœ์ ์…˜ ์•ˆ์—์„œ๋Š” ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค - ์•ฝ๊ฐ„์˜ ์กฐํšŒ ์„ฑ๋Šฅ ํ–ฅ์ƒ
      • DB Isolation Level์ด Read Commit์ด์–ด๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Repeatable Read๋ฅผ ๋ณด์žฅํ•œ๋‹ค.
    2. ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋Š” ์“ฐ๊ธฐ

      • ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•  ๋•Œ๊ฐ€์ง€ INSERT SQL์„ ๋ชจ์€๋‹ค
      • ๊ทธํ›„ JDBC BAT SQL ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์„œ ํ•œ๋ฒˆ์— SQL์— ์ „์†กํ•œ๋‹ค.

      ๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ๋ฒˆ์˜ ํŠธ๋žœ์ง์…˜์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  1๋ฒˆ๋งŒ ๋ฐœ์ƒํ•˜์—ฌ ์„ฑ๋Šฅ์ด ์ข‹๋‹ค.

    3. ์ฆ‰์‹œ ๋กœ๋”ฉ๊ณผ ์ง€์—ฐ ๋กœ๋”ฉ

      • ์ง€์—ฐ ๋กœ๋”ฉ: ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ ์‚ฌ์šฉ๋  ๋•Œ ๋กœ๋”ฉ๋œ๋‹ค.
      • ์ฆ‰์‹œ ๋กœ๋”ฉ: JOIN SQL๋กœ ํ•œ๋ฒˆ์— ์—ฐ๊ด€๋œ ๊ฐ์ฒด๊นŒ์ง€ ๋ฏธ๋ฆฌ ์กฐํšŒํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฉค๋ฒ„๋ฅผ ์กฐํšŒํ•  ๋•Œ ํ•ญ์ƒ ํŒ€๋„ ์กฐํšŒํ•ด์•ผ๋œ๋‹ค๋ฉด ์„ค์ •์„ ์ผœ์„œ ํ•ญ์ƒ ๋‘˜์ด ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.
  5. ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ์ถ”์ƒํ™”์™€ ๋ฒค๋” ๋…๋ฆฝ์„ฑ

  6. ํ‘œ์ค€

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐฉ์–ธ

  1. JPA๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ข…์†๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค. ๊ทน๋‹จ์ ์ธ ์˜ˆ๋กœ MySQL์—์„œ ORACLE๋กœ DB๋ฅผ ๋ฐ”๊ฟ”๋„ ํฌ๊ฒŒ ์† ๋ณผ ๊ฒƒ์ด ์—†๋‹ค.

  2. ๊ธฐ์กด์—๋Š” ๊ฐ๊ฐ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” SQL ๋ฌธ๋ฒ•๊ณผ ํ•จ์ˆ˜๋Š” ์„œ๋กœ ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด,

    • ๊ฐ€๋ณ€ ๋ฌธ์ž: MySQL์€ VARCHAR - Oracle์€ VARCHAR2
    • ๋ฌธ์ž์—ด์„ ์ž๋ฅด๋Š” ํ•จ์ˆ˜: SQL ํ‘œ์ค€์€ SUBSTRING(), Oracle์€ SUBSTR()
    • ํŽ˜์ด์ง•: MySQL์€ LIMIT, Oracle์€ ROWNUM ์œผ๋กœ ์„œ๋กœ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.
  3. ๋ฐฉ์–ธ์ด๋ž€: SQL ํ‘œ์ค€์„ ์ง€ํ‚ค์ง€ ์•Š๋Š” ํŠน์ •๋ฐ์ดํ„ฐ๋ฉ”์ด์Šค๋งŒ์˜ ๊ณ ์œ ํ•œ ๊ธฐ๋Šฅ์ด๋‹ค. ์ด๊ฒƒ์€ JPA ์ž…์žฅ์—์„œ ๋ฐฉ์–ธ์ด๋ผ๊ณ  ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ˜„์žฌ H2 ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์“ฐ๊ณ  ์žˆ๋‹ค. ์ด๋Š” SQL ํ‘œ์ค€ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  H2๋งŒ์˜ ๋ฐฉ์–ธ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, JPA๊ฐ€ ์•Œ์•„์„œ ํ‘œ์ค€์œผ๋กœ ๋ฒˆ์—ญํ•ด์„œ ์ „๋‹ฌํ•ด ์ค€๋‹ค.

image

JPA ๊ตฌ๋™ ๋ฐฉ์‹

  1. Jpa๋Š” Persistence๋ผ๋Š” ํด๋ž˜์Šค์—์„œ ์‹œ์ž‘์„ ํ•œ๋‹ค.
  2. Persistence๋Š” ๊ฐ€์žฅ ๋งŒ์ € META-INF/persistence.xml ์—์„œ ์„ค์ • ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.
  3. ์กฐํšŒํ•œ ์„ค์ • ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ EntityManagerFactory๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค
  4. ๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค Factory(๊ณต์žฅ)์—์„œ EntityManager์ด๋ผ๋Š” ๊ฒƒ์„ ์ฐ์–ด๋‚ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

โ€‹ ์ฃผ์˜!

  1. JPA๋Š” ํŠธ๋ Œ์ ์…˜ ๋‹จ์œ„๋กœ ์ž‘๋™์‹œํ‚ค๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ชจ๋“  ์ž‘์—…์€ ํŠธ๋ Œ์ ์…˜ ์•ˆ์—์„œ ์‹คํ–‰๋˜์–ด์•ผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ em.getTransaction์„ ์‹œ์ž‘ํ•˜๊ณ  ๋๋‚˜๋Š” ์ง€์ ์„ ์ •ํ•ด์ค˜์„œ ํ•˜๋‚˜์˜ ํŠธ๋ Œ์ ์…˜์„ ์„ ์–ธํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

  2. EntitiyManagerFactory๋Š” ๋งจ ์ฒ˜์Œ ๋กœ๋”ฉ ์‹œ์ ์— ๋”ฑ ํ•œ๋ฒˆ๋งŒ ๋งŒ๋“ค์–ด ๋†“์•„์•ผํ•œ๋‹ค.

  3. ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €๋Š” ์“ฐ๋ž˜๋“œ๊ฐ„ ๊ณต์œ  X (์‚ฌ์šฉํ•˜๊ณ  ๋ฒ„๋ ค์•ผ ํ•œ๋‹ค.) ๋”ฐ๋ผ์„œ DB์— ์ €์žฅ๋˜๋Š” ํŠธ๋žœ์ ์…˜ ๋‹จ์œ„๋ฅผ ํ• ๋•Œ๋งˆ๋‹ค EntityManager์„ ๋งŒ๋“ค์–ด ์ฃผ์–ด์•ผํ•œ๋‹ค.

โ€‹ *ํŠธ๋ Œ์ ์…˜: ex) ๊ณ ๊ฐ์ด ๋“ค์–ด์™€์„œ ์–ด๋–ค ํ–‰์œ„๋ฅผ ํ•˜๊ณ  ๋‚˜๊ฐˆ๋•Œ๋งˆ๋‹ค ์šฐ๋ฆฌ๋Š” ๊ณ ๊ฐ์˜ ๋””๋น„ ์ปค๋‚ต์…˜์„ ์–ป์–ด์„œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๊ณ  ์ข…๋ฃŒํ•ด์•ผํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์–ด๋–ค ํ–‰์œ„๋ฅผ ํ•  ๋•Œ ๋”” ๋น„๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์ข…๋ฃŒํ•  ๋•Œ๊นŒ์ง€๋ฅผ ํ•œ ๋ฌถ์Œ์œผ๋กœ ์ผ๊ด€๋˜๋Š” ๋‹จ์œ„

image

๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ณ  ๋งคํ•‘ํ•˜๊ธฐ

create table Member(
  id bigint not null,
  name varchar(255),
  primary key (id)
);MEMBER 

;

@Entity
public class Member {

    @Id
    private Long id; // pk ๊ฐ’
    private String name;
}

JpaMain ํด๋ž˜์Šค

  1. ์ดˆ๊ธฐ ์ž‘์„ฑ ํ˜•์‹
// Entity ๊ณต์žฅ ์ƒ์„ฑ - ๊ณต์žฅ ์ƒ์„ฑ์€ ํ•œ๋ฒˆ๋งŒ.
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("hello");// ํŒŒ๋ผ๋ฏธํ„ฐ ์•ˆ์—๋Š” persistense.xml์— ์žˆ๋Š” unit ์ด๋ฆ„์„ ๋„ฃ์–ด์ค€๋‹ค.

        // Entity Manager ๊ฐ์ฒด ์ƒ์„ฑ - ํŠธ๋ Œ์ ์…˜ ๋‹จ์œ„๋กœ ๋งค๋ฒˆ ์ƒ์„ฑ.
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        // ํ•„์š”ํ•œ Entity Manager ์ฝ”๋“œ ์ž‘์„ฑ
        EntityTransaction transaction = entityManager.getTransaction(); // ํŠธ๋ Œ์ ์…˜ ์„ ์–ธ

        try { // ์˜ค๋ฅ˜๋ฅผ ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•ด try, catch๋ฌธ ์‚ฌ์šฉ.
            transaction.begin(); // ํŠธ๋ Œ์ ์…˜ ์‹œ์ž‘.
            // ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ
            transaction.commit(); // ํŠธ๋ Œ์ ์…˜ ์ข…๋ฃŒ - ์ปค๋ฐ‹ ์‹œ์ ์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์žˆ๋Š” ๋‚ด์šฉ์ด DB์— ์ €์žฅ๋œ๋‹ค.
        } catch(Exception e){
            transaction.rollback(); // ์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œ ๋กค๋ฐฑ ํ•ด์ฃผ๊ธฐ
        } finally{
            entityManager.close();
        }
  1. ๋ฉค๋ฒ„ ์ €์žฅ
       try { // ์˜ค๋ฅ˜๋ฅผ ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•ด try, catch๋ฌธ ์‚ฌ์šฉ.
            transaction.begin(); // ํŠธ๋ Œ์ ์…˜ ์‹œ์ž‘.
            Member member = new Member();
            member.setId(3L);
            member.setName("HelloC");

            entityManager.persist(member); // ๊ฐ์ฒด๋ฅผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ. ๊ทธํ›„ ๋””๋น„ ์ €์žฅ.

            transaction.commit(); // ํŠธ๋ Œ์ ์…˜ ์ข…๋ฃŒ - ์ปค๋ฐ‹ ์‹œ์ ์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์žˆ๋Š” ๋‚ด์šฉ์ด DB์— ์ €์žฅ๋œ๋‹ค.
        } catch(Exception e){
            transaction.rollback(); // ์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œ ๋กค๋ฐฑ ํ•ด์ฃผ๊ธฐ
        } finally{
            entityManager.close();
        }
  1. ๋ฉค๋ฒ„ ์กฐํšŒ
try { // ์˜ค๋ฅ˜๋ฅผ ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•ด try, catch๋ฌธ ์‚ฌ์šฉ.
            transaction.begin(); // ํŠธ๋ Œ์ ์…˜ ์‹œ์ž‘.

            Member findMember = entityManager.find(Member.class, 1L); // ํด๋ ˆ์Šค ์ด๋ฆ„, ID๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด ์ฐพ๋Š”๋‹ค
            System.out.println("findMember.id = " + findMember.getId());
            System.out.println("findMember.Name = " + findMember.getName());

            transaction.commit(); // ํŠธ๋ Œ์ ์…˜ ์ข…๋ฃŒ - ์ปค๋ฐ‹ ์‹œ์ ์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์žˆ๋Š” ๋‚ด์šฉ์ด DB์— ์ €์žฅ๋œ๋‹ค.
        } catch(Exception e){
            transaction.rollback();
        } finally{
            entityManager.close();
        }
  1. ๋ฉค๋ฒ„ ์ˆ˜์ •
try { // ์˜ค๋ฅ˜๋ฅผ ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•ด try, catch๋ฌธ ์‚ฌ์šฉ.
            transaction.begin(); // ํŠธ๋ Œ์ ์…˜ ์‹œ์ž‘.

            Member findMember = entityManager.find(Member.class, 1L); // ํด๋ ˆ์Šค ์ด๋ฆ„, ID๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด ์ฐพ๋Š”๋‹ค
            findMember.setName("HelloJPA"); // ๋ณ€๊ฒฝ๋œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด jPA๊ฐ€ ์—…๋ฐ์ดํŠธ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•ด์„œ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

    transaction.commit(); // ํŠธ๋ Œ์ ์…˜ ์ข…๋ฃŒ - ์ปค๋ฐ‹ ์‹œ์ ์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์žˆ๋Š” ๋‚ด์šฉ์ด DB์— ์ €์žฅ๋œ๋‹ค.
        } catch(Exception e){
            transaction.rollback();
        } finally{
            entityManager.close();
        }
  1. ๋ฉค๋ฒ„ ์‚ญ์ œ
try { // ์˜ค๋ฅ˜๋ฅผ ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•ด try, catch๋ฌธ ์‚ฌ์šฉ.
    transaction.begin(); // ํŠธ๋ Œ์ ์…˜ ์‹œ์ž‘.
    entityManager.remove(findMember);
	
    transaction.commit(); // ํŠธ๋ Œ์ ์…˜ ์ข…๋ฃŒ - ์ปค๋ฐ‹ ์‹œ์ ์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์žˆ๋Š” ๋‚ด์šฉ์ด DB์— ์ €์žฅ๋œ๋‹ค.
    } catch(Exception e){
    	transaction.rollback();
	} finally{
		entityManager.close();
	}

JPQL ์†Œ๊ฐœ

JPA์—์„œ๋Š” SQL์„ ์ถ”์ƒํ™”ํ•œ JPQL์ด๋ผ๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. ์ด๋Š” SQL๊ณผ ๋ฌธ๋ฒ•์ด ์œ ์‚ฌํ•˜๋‹ค. SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN ๋“ฑ์„ ์ง€์›ํ•œ๋‹ค.

์ฐจ์ด์ :

  1. JPQL์€ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
  2. SQL์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

JPQL์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌด์—‡์ด ๋ฉ”๋ฆฌํŠธ์ธ๊ฐ€?

  1. ํŽ˜์ด์ง• ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ํ•  ๋•Œ DB ๋ฐฉ์–ธ์„ ์•Œ์•„์„œ ๋งž์ถฐ์„œ ์‚ฌ์šฉํ•ด์ค€๋‹ค. ๋”ฐ๋ผ์„œ DB๋ฅผ ๋ฐ”๊ฟ”๋„ ์ฝ”๋“œ๋ฅผ ๊ฑฐ์˜ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

  2. ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์ž‘์„ฑ์ด๋‹ค.

  3. ํ•ญ์ƒ ๋ฌธ์ œ๋Š” ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์—์„œ ์ƒ๋Š”๋ฐ, DB๊ฐ€ ์•„๋‹Œ Entity ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

  4. ๊ธฐ์กด์—๋Š” ๋ชจ๋“  DB ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค

  5. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ DB์—์„œ ๋ถˆ๋Ÿฌ์˜ค๋ ค๋ฉด ๊ฒฐ๊ตญ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์ด ํฌํ•จ๋œ SQL์ด ํ•„์š”ํ•œ๋‹ค. ํ•˜์ง€๋งŒ RDB์˜ ์‹ค์ œ ๋ฌผ๋ฆฌ์ ์ธ ํ…Œ์ด๋ธ”์„ ๊ฐ€์ ธ์˜ค๋ฉด ์ข…์†์ ์œผ๋กœ ์„ค๊ณ„๊ฐ€ ๋˜์–ด ์•ˆ์ข‹๋‹ค. ๋”ฐ๋ผ์„œ JPA๋Š” SQl์„ ์ถ”์ƒํ™”ํ•œ JPQL์ด๋ผ๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ข…์†์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

  • ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ์กฐํšŒ ๋ฐฉ๋ฒ•
    • EntityManager.find()
    • ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰(a.getB().getC())
  • ํ•˜์ง€๋งŒ ๋‚˜์ด๊ฐ€ 18์‚ด ์ด์ƒ์ธ ํšŒ์›์„ ๋ชจ๋‘ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

์‹ค์Šต

JPA ์ž…์žฅ์—์„œ๋Š” DB ํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ ์ ˆ๋•Œ ์ฝ”๋“œ๋ฅผ ์งœ์ง€ ์•Š๋Š”๋‹ค. JPA๋Š” ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ง ๋‹ค.

  1. ์กฐํšŒ: List<Member> result = em.createQuery("select m from Member as m", Member.class).getResultList();

์˜์†์„ฑ ๊ด€๋ฆฌ - JPA ๋‚ด๋ถ€ ๊ตฌ์กฐ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

JPA๋ฅผ ์ดํ•ดํ•˜๋ ค๋ฉด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ผ๋Š” ๊ฒƒ์„ ๋จผ์ € ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

JPA์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ 2๊ฐ€์ง€:

  • ๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งคํ•‘ํ•˜๊ธฐ - ์„ค๊ณ„/์ •์ ์ธ ๋ถ€๋ถ„

  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ - ์‹ค์ œ JPA ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์— ๋Œ€ํ•œ ๋ถ€๋ถ„

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๋Š” ์ˆœ์„œ

  1. ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ํŒฉํ† ๋ฆฌ์—์„œ๋Š” ๊ณ ๊ฐ์˜ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

  2. ๋งŒ๋“ค์–ด ์ง„ ์—”ํ‹ฐํ‹ฐ ๋ฉ”์ด์ €๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜ ํ’€์— ์žˆ๋Š” ์ปค๋‚ต์…˜์„ ์‚ฌ์šฉํ•ด์„œ ๋””๋น„๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ž€?

JPA๋ฅผ ์ดํ•ดํ•˜๋Š”๋ฐ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์šฉ์–ด์ด๋‹ค.

์˜๋ฏธ: "์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜๊ตฌ ์ €์žฅํ•˜๋Š” ํ™˜๊ฒฝ"์ด๋ผ๋Š” ๋œป. ํ•˜์ง€๋งŒ ๋…ผ๋ฆฌ์ ์ธ ๊ฐœ๋…์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ˆˆ์— ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค.

์ฝ”๋“œ: EntityManager.persist(entity); // ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์†์„ฑ ์ปจํ…Œ์ŠคํŠธ๋ผ๋Š” ๊ณณ์— ์ €์žฅ์„ ํ•œ๋‹ค๋Š” ์˜๋ฏธ.

์—”ํ‹ฐํ‹ฐ์˜ ์ƒ๋ช…์ฃผ๊ธฐ

  1. ๋น„์˜์†(new/transient): ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ ์ „ํ˜€ ๊ด€๊ณ„๊ฐ€ ์—†๋Š” ์ƒˆ๋กœ์šด ์ƒํƒœ

    • ๊ฐ์ฒด๋งŒ ์ƒ์„ฑํ•œ ์ƒํƒœ

    • Member member = new Member();
      member.setId("member1");
      member.setUsername("ํšŒ์›1");
  2. ์˜์†(managed): ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๊ด€๋ฆฌ๋˜๋Š” ์ƒํƒœ

    • ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ํ›„ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•œ ์ƒํƒœ(์˜์†)

    • Member member = new Member();
      member.setId("member1");
      member.setUsername("ํšŒ์›1");
      
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      
      em.persist(member); // ๊ฐ์ฒด๋ฅผ ์ €์ž—ํ•œ ์ƒํƒœ(์˜์†) 
    • DB์ €์žฅ์€ ํŠธ๋ Œ์ ์…˜์„ commit ํ•˜๋Š” ๊ฒฝ์šฐ์— ๋””๋น„์— ์ฟผ๋ฆฌ๊ฐ€ ๋‚ ๋ผ๊ฐ€๊ฒŒ๋œ๋‹ค.

  3. ์ค€์˜์†(detached): ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋˜์—ˆ๋‹ค๊ฐ€ ๋ถ„๋ฆฌ๋œ ์ƒํƒœ

    • em.detach(member);
  4. ์‚ญ์ œ(removed): ์‚ญ์ œ๋œ ์ƒํƒœ

    • em.remove(member);

์ด๋Š” DBํ•˜๊ณ  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ค‘๊ฐ„์— ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•˜๋‚˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ์ด์ :

  1. 1์ฐจ ์บ์‹œ
  2. ๋™์ผ์„ฑ ๋ณด์žฅ
  3. ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋Š” ์“ฐ๊ธฐ ์ง€์—ฐ
  4. ๋ณ€๊ฒฝ ๊ฐ์ง€
  5. ์ง€์—ฐ ๋กœ๋”ฉ

์—”ํ‹ฐํ‹ฐ ๋งคํ•‘

1. ๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ” ๋งคํ•‘

@Entiti: @Entity๊ฐ€ ๋ถ™์€ ํด๋ž˜์Šค๋Š” JPA๊ฐ€ ๊ด€๋ฆฌ, ์—”ํ‹ฐํ‹ฐ๋ผ ํ•œ๋‹ค. JPA๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ•  ํด๋ž˜์Šค๋Š” @Entity๊ฐ€ ํ•„์ˆ˜๋กœ ์ž‘์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค.

์ฃผ์˜:

  1. ๊ธฐ๋ณธ ์ƒ์„ฑ์ž ํ•„์ˆ˜(ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋Š” public ๋˜๋Š” protected ์ƒ์„ฑ์ž)
  2. final ํด๋ž˜์Šค, enum, interface, inner ํด๋ž˜์Šค๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
  3. ์ €์žฅํ•  ํ•„๋“œ์— final์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ธˆ์ง€!!

2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ์ž๋™ ์ƒ์„ฑ

์˜ต์…˜ ์„ค๋ช…
create ๊ธฐ์กดํ…Œ์ด๋ธ” ์‚ญ์ œ ํ›„ ๋‹ค์‹œ ์ƒ์„ฑ(DROP+CREATE)
create-drop create์™€ ๊ฐ™์œผ๋‚˜ ์ข…๋ฃŒ ์‹œ์ ์— ํ…Œ์ด๋ธ” DROP
update ๋ณ€๊ฒฝ๋ถ„๋งŒ ๋ฐ˜์˜(์šด์˜DB์—๋Š” ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋จ)
validate ์—”ํ‹ฐํ‹ฐ์™€ ํ…Œ์ด๋ธ”์ด ์ •์ƒ ๋งคํ•‘๋˜์—ˆ๋Š”์ง€๋งŒ ํ™•์ธ
none ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

์ฃผ์˜: ์šด์˜ ์žฅ๋น„์—๋Š” ์ ˆ๋Œ€ Create, Create-drop, update๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค!!!!

  • ๊ฐœ๋ฐœ ์ดˆ๊ธฐ ๋‹จ๊ณ„๋Š” create ๋˜๋Š” update

  • ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๋Š” update ๋˜๋Š” validate

  • ์Šคํ…Œ์ด์ง•๊ณผ ์šด์˜ ์„œ๋ฒ„๋Š” validate ๋˜๋Š” none - ํ•˜์ง€๋งŒ ์ตœ๋Œ€ํ•œ ์“ฐ์ง€๋ง ๊ฒƒ

์ƒ์†๊ด€๊ณ„ ๋งคํ•‘

์ƒ์†๊ด€๊ณ„ ๋งคํ•‘ : ๊ฐ์ฒด์˜ ์ƒ์† ๊ตฌ์กฐ์™€ DB์˜ ์Šˆํผํƒ€์ž… ์„œ๋ธŒํƒ€์ž… ๊ด€๊ณ„๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ๋…ผ๋ฆฌ ๋ชจ๋ธ์„ ๋ณด๋ฉด, ๋ฌผํ’ˆ์ด๋ผ๋Š” ์Šˆํผ ํƒ€์ž…์—๋Š” ์Œ๋ฐ˜, ์˜ํ™”, ์ฑ…์ด๋ผ๋Š” ์„œ๋ธŒํƒ€์ž…๋“ค ๊ฐ„์˜ ๊ณตํ†ต์ ์ธ ์†์„ฑ ํ™œ์šฉํ•˜์—ฌ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ์ฒด๋Š” ๋ช…ํ™•ํ•˜๊ฒŒ ์ƒ์† ๊ด€๊ณ„๊ฐ€ ์žˆ์ง€๋งŒ, ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ƒ์† ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์ด์ฒ˜๋Ÿผ ์Šˆํผํƒ€์ž…, ์„œ๋ธŒํƒ€์ž…์ด๋ผ๋Š” ๊ด€๊ณ„๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ๋ง ๊ธฐ๋ฒ•์ด ๊ฐ์ฒด ์ƒ์†๊ณผ ์ตœ๋Œ€ํ•œ ์œ ์‚ฌํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์‹œ๋งํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ํฌ์ธํŠธ๋Š”, ์Šˆํผ ํƒ€์ž… ํ…Œ์ด๋ธ”์ด ์„œ๋ธŒ ํƒ€์ž… ํ…Œ์ด๋ธ”์˜ ๋‚ด์šฉ ํ˜น์€ ์„œ๋ธŒ ํƒ€์ž… ํ…Œ์ด๋ธ”์ด ์Šˆํผํƒ€์ž… ํ…Œ์ด๋ธ”์˜ ๋‚ด์šฉ์„ ์–ด๋–ป๊ฒŒ ๊ฐ€์ ธ์˜ฌ์ˆ˜ ์žˆ๋Š๋ƒ์ด๋‹ค. ๊ณตํ†ต์ ์„ ์Šˆํผํƒ€์ž…์— ๋‹ค ๋ชฐ์•„๋„ฃ๊ณ  ์„œ๋ธŒ ํƒ€์ž…์— ๊ทธ ๊ณตํ†ต์ ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ๋งŒ์ด ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค.

image

์ƒ์†๊ด€๊ณ„ ๋งคํ•‘ ๊ตฌํ˜„ํ•˜๋Š” 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•(=๋…ผ๋ฆฌ ๋ชจ๋ธ์„ ๋ฌผ๋ฆฌ ๋ชจ๋ธ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•)

  1. ์กฐ์ธ ์ „๋žต: ๊ฐ๊ฐ ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜ - DB JOIN์„ ํ™œ์šฉํ•˜์—ฌ ์„œ๋ธŒ๋ชจ๋ธ์˜ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜จ๋‹ค. ์ด๋Š” ์„œ๋ธŒ ํƒ€์ž…์˜ ๊ณตํ†ต์ ์„ ์Šˆํผํƒ€์ž…์—๋งŒ ์ €์žฅํ•ด ๋†“๊ณ  ์‚ฌ์šฉํ•˜๋Š”, ์šฐ๋ฆฌ๊ฐ€ ์•„๋Š” ๊ฐ€์žฅ ํ”ํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด๋•Œ ์„œ๋ธŒ ํ…Œ์ด๋ธ”๋“ค์„ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์Šˆํผํƒ€์ž…์˜ ์†์„ฑ์—๋Š” Dtype๊ณผ ๊ฐ™์€ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. image
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // join ์ „๋žต์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•
@DiscriminatorColumn // ์Šˆํผ ํƒ€์ž…์˜ Dtype ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ  ์„œ๋ธŒ ํƒ€์ž…์˜ ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ ๋‚ด์šฉ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค.
// ์„œ๋ธŒ ํƒ€์ž…์—๋Š” @DiscriminatorValue()๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์€ ํด๋ ˆ์Šค ๋ช…์ด์ง€๋งŒ, ๋งŒ์•ฝ์— dtype ๋‚ด์šฉ์„ ํŠน์ •ํ•œ ๋‚ด์šฉ์œผ๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด @DiscriminatorValue("A")์™€ ๊ฐ™์ด ์จ์ฃผ๋ฉด ๋œ๋‹ค.

public abstract class Item {
    @Id @GeneratedValue
    private Long id;
    
    private String name; 
    private int price; 
    ...
  • ์กฐ์ธ ์ „๋žต์˜ ์žฅ์ :
    1. ํ…Œ์ด๋ธ”์ด ์ •๊ทœํ™” ๋˜์–ด์žˆ๊ณ 
    2. ์™ธ๋ž˜ํ‚ค ์ฐธ์กฐ ๋ฌด๊ฒฐ์„ฑ ์ œ์•ฝ์กฐ๊ฑด ํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. - ์ฃผ๋ฌธ ์•„์ดํ…œ์ด ํ•„์š”ํ• ๋•Œ ์•„์ดํ…œ ํ…Œ์ด๋ธ”๋งŒ ๋ด๋„ ๋œ๋‹ค.
    3. ์ €์žฅ๊ณต๊ฐ„์˜ ํšจ์œจํ™”
  • ์กฐ์ธ ์ „๋žต์˜ ๋‹จ์  :
    1. ์กฐํšŒ์‹œ ์กฐ์ธ์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์–ด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋œ๋‹ค.
    2. ์กฐํšŒ ์ฟผ๋ฆฌ๊ฐ€ ๋ณต์žกํ•˜๋‹ค.
    3. ๋ฐ์ดํ„ฐ ์ €์žฅ ์‹œ Insert SQL์ด 2๋ฒˆ ํ˜ธ์ถœ๋œ๋‹ค.
    4. ๋‹จ์ผ ํ…Œ์ด๋ธ”์— ๋น„ํ•ด์„œ ๊ด€๋ฆฌํ•˜๊ธฐ ๋ณต์žกํ•˜๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค ๋ชจ๋‘ ํฐ ๋‹จ์ ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์กฐ์ธ ์ „๋žต์„ ๋ฉ”์ธ์œผ๋กœ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  1. ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต(@inheritance(strategy=InheritanceType.SINGLE_TABLE): ํ†ตํ•ฉ ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜ - ์„œ๋ธŒ ํƒ€์ž…์˜ ๋ชจ๋“  ์†์„ฑ์„ ์Šˆํผํƒ€์ž…์— ๋ชจ๋‘ ๋„ฃ์–ด์„œ ํ…Œ์ด๋ธ” ํ•˜๋‚˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Š” dtype์œผ๋กœ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค. ๋‹จ์ผ ํ…Œ์ด๋ธ”์€ @DiscriminatorColumn์ด ์—†์–ด๋„ ํ•„์ˆ˜๋กœ dtype์ด ์ƒ์„ฑ๋œ๋‹ค.
  • ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต์˜ ์žฅ์ :
    1. ์กฐ์ธ์ด ํ•„์š”์—†๊ณ  select ํ•œ๋ฒˆ๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋ฏ€๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์กฐํšŒ ์„ฑ๋Šฅ์ด ๋น ๋ฅด๋‹ค.
    2. ์กฐํšŒ ์ฟผ๋ฆฌ๊ฐ€ ๋‹จ์ˆœํ•˜๋‹ค.
  • ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต์˜ ๋‹จ์ :
    1. **์ž์‹ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋งคํ•‘ํ•œ ์ปฌ๋Ÿผ์€ ๋ชจ๋‘ null ํ—ˆ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ์น˜๋ช…์ ์ธ ๋‹จ์ ์ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ์ž…์žฅ์—์„œ๋Š” ์• ๋งคํ•˜๋‹ค.
    2. ๋‹จ์ผ ํ…Œ์ด๋ธ”์— ๋ชจ๋“  ๊ฒƒ์„ ์ €์žฅํ•˜๋ฏ€๋กœ ํ…Œ์ด๋ธ”์ด ์ปค์งˆ์ˆ˜ ์žˆ์–ด์„œ, ์ƒํ™ฉ์— ๋”ฐ๋ผ ์กฐํšŒ ์ „๋žต๋ณด๋‹ค ์„ฑ๋Šฅ์ด ์•ˆ์ข‹์•„์งˆ ์ˆ˜ ์žˆ๋‹ค.
  1. ๊ตฌํ˜„ ํด๋ž˜์Šค๋งˆ๋‹ค ํ…Œ์ด๋ธ” ์ „๋žต(@inheritance(strategy=InheritanceType.TABLE_PER_CLASS): ์„œ๋ธŒํƒ€์ž… ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜ - ๊ฐ ์„œ๋ธŒ ํƒ€์ž…๋“ค์ด ๊ณตํ†ต์ ์„ ์Šˆํผ ํƒ€์ž…์— ๋„ฃ์–ด๋†“๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ฐ์ž ๋ชจ๋‘ ๋‹ค ๊ฐ€์ง€๋„๋ก ์ค‘๋ณต์„ ํ—ˆ์šฉํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ „๋žต์„ ์„œ๋กœ ๋ฌถ์ด๋Š” ๊ฒƒ์ด ์—†์–ด์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„์ž์™€ ORM ์ „๋ฌธ๊ฐ€ ๋ชจ๋‘ ์ถ”์ฒœํ•˜์ง€ ์•Š๋Š” ์ „๋žต์ด๋‹ค
  • ๊ตฌํ˜„ ํด๋ž˜์Šค ์ „๋žต์˜ ์žฅ์ :
    1. ์„œ๋ธŒ ํƒ€์ž…์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•ด์„œ ์ฒ˜๋ฆฌํ•  ๋•Œ ํšจ๊ณผ์ ์ด๋‹ค.
    2. not null ์ œ์•ฝ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ตฌํ˜„ ํด๋ž˜์Šค ์ „๋žต์˜ ๋‹จ์ :
    1. ์—ฌ๋Ÿฌ ์ž์‹ ํ…Œ์ด๋ธ”์„ ํ•จ๊ป˜ ์กฐํšŒํ•  ๋•Œ ์„ฑ๋Šฅ์ด ๋Š๋ฆฌ๋‹ค(UNION SQL)
    2. ์ž์‹ ํ…Œ์ด๋ธ”์„ ํ†ตํ•ฉํ•ด์„œ ์ฟผ๋ฆฌํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
    3. ์ƒˆ๋กœ์šด ํƒ€์ž…์ด ์ถ”๊ฐ€๊ฐ€ ๋ ๋•Œ(=๋ณ€๊ฒฝ์ด ๋ ๋•Œ) ๋ณ€๊ฒฝํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ํž˜๋“ค๋‹ค.

=> ์ด ์ค‘ ์–ด๋–ค ๋ฐฉ๋ฒ•์œผ๋กœ ๊ด€๊ณ„๋งคํ•‘์„ ํ•˜๋”๋ผ๋„ JPA๋Š” ๋ชจ๋‘ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

@MappedSuperclass

@MappedSuperclass๋Š” ๊ฐ์ฒด ์ž…์žฅ์—์„œ name, id์™€ ๊ฐ™์€ ์†์„ฑ์ด ๋งŽ์€ ํด๋ž˜์Šค์—์„œ ๊ณ„์† ๋‚˜์˜ฌ ๊ฒฝ์šฐ, ์ด ๋ถˆํŽธํ•จ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ณตํ†ต ๋งคํ•‘ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค. ๋”ฑ ๊ณตํ†ต ๋งคํ•‘ ์ •๋ณด๋ฅผ ๋ฟŒ๋ ค์ฃผ๊ธฐ ์œ„ํ•œ ๋„๊ตฌ ์ •๋„์ผ ๋ฟ์ด๋‹ค.

  • ํ…Œ์ด๋ธ”๊ณผ ๊ด€๊ณ„๊ฐ€ ์—†๊ณ , ๋‹จ์ˆœํžˆ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋งคํ•‘ ์ •๋ณด๋ฅผ ๋ชจ์œผ๋Š” ์—ญํ• ์ด๋‹ค.

  • ์ฃผ๋กœ ๋“ฑ๋ก์ผ, ์ˆ˜์ •์ผ, ๋“ฑ๋ก์ž, ์ˆ˜์ •์ž ๊ฐ™์€ ์ „์ฒด ์—”ํ‹ฐํ‹ฐ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉํ•˜๋Š” ์ •๋ณด๋ฅผ ๋ชจ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

  • cf) @Entity ํด๋ž˜์Šค๋Š” ์—”ํ‹ฐํ‹ฐ๋‚˜ @MappedSuperclass๋กœ ์ง€์ •ํ•œ ํด๋ž˜์Šค๋งŒ ์ƒ์† ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ํŠน์ง•:

    1. ์ƒ์†๊ด€๊ณ„์— ๋งคํ•‘๋˜์ง€ ์•Š๋Š”๋‹ค
    2. ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์•„๋‹ˆ๊ธฐ๋•Œ๋ฌธ์—, ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋˜์ง€ ์•Š๋Š”๋‹ค.
    3. ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›๋Š” ์ž์‹ ํด๋ž˜์Šค์— ๋งคํ•‘ ์ •๋ณด๋งŒ์„ ์ œ๊ณตํ•œ๋‹ค.
    4. ์กฐํšŒ, ๊ฒ€์ƒ‰์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. em.find(BaseEntity) ์‚ฌ์šฉ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
    5. ์ง์ ‘ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•  ์ผ์ด ์—†์œผ๋ฏ€๋กœ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค๊ธธ ๊ถŒ์žฅํ•œ๋‹ค.
@MappedSuperclass
public abstract class BaseEntity {
	private String createBy;
	private LocalDateTime createdDate;
	private String lastModifiedBy;
	private LocalDateTime lastModifiedDate;

	public String getCreatedBy() {
		return createBy;
	}
	// ๊ฐ ์†์„ฑ์˜ getter, setter ๊ธฐ์ž…
	...
}
	
@Entity
public class Member extends BaseEntity {
	// ์ด์ „ ๋‚ด์šฉ๊ณผ ๋™์ผ
	...
	
// JpaMain.class
// ์ด์ „ ๋‚ด์šฉ๊ณผ ๋™์ผ
...
try {
	Member member = new Member();
	member.setUsername("user1");
	member.setCreatedBy("kim");
	member.setCreatedDate(localDateTime.new());
	
	em.persist(member);
	em.flush();
	em.clear();
	
	tx.commit();
}
	
// ์ด์ „ ๋‚ด์šฉ๊ณผ ๋™์ผ 
...	

์ด๋ ‡๊ฒŒ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์— ํ•„์š”ํ•œ ์†์„ฑ์„ ์ง‘์–ด๋„ฃ๊ณ  ๊ฐ ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ๊ฐ ํด๋ž˜์Šค๋Š” ์ถ”๊ฐ€์ ์ธ ์ฝ”๋“œ๊ฐ€ ํ•„์š”์—†์ด ํ•ด๋‹น ์†์„ฑ๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค. ์ฝ”๋”ฉํ• ๋•Œ ๊ต‰์žฅํžˆ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์€ ๊ฒƒ ๊ฐ™๋‹ค.

image

##ํ”„๋ก์‹œ!! ํ”„๋ก์‹œ๋ฅผ ์™œ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ? ์šฐ๋ฆฌ๋Š” ์ฝ”๋“œ๋ฅผ ์งค๋•Œ Member๊ณผ Team์œผ๋กœ(์ฒ˜๋Ÿผ) ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š” ํ…Œ์ด๋ธ”์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ Member๋งŒ ์ถœ๋ ฅํ•˜๋ฉด ๋˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ์ผ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๊ณ , Member์™€ Team์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ๋˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ์ผ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. Member๋งŒ ์ถœ๋ ฅํ•ด์•ผ๋ ๋•Œ๋Š” ๊ทธ๋Ÿผ ๋‚ญ๋น„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด ๋‚ญ๋น„๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด ํ”„๋ก์‹œ๋ผ๋Š” ๊ฒƒ์ด ์กด์žฌํ•œ๋‹ค.

ํ”„๋ก์‹œ์˜ ๊ธฐ์ดˆ - em.getReference()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

  • ๊ธฐ์กด์˜ em.find()์™€ em.**getReference()**๋ฅผ ๋น„๊ตํ•ด๋ณด์ž.
  • em.find()๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ•œ๋‹ค.
  • em.getReference()๋Š” **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ๋ฅผ ๋ฏธ๋ฃจ๋Š” ๊ฐ€์งœ(ํ”„๋ก์‹œ) ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋Š” ๋””๋น„์— ์ฟผ๋ฆฌ๊ฐ€ ์•ˆ๋‚˜๊ฐ€๋Š”๋ฐ๋„ ๊ฐ์ฒด๊ฐ€ ์กฐํšŒ๊ฐ€ ๋œ๋‹ค. ์ด๋Š” ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๊ฐ€ ์ž๊ธฐ ๋‚ด๋ถ€์˜ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋งŒ๋“ ๋‹ค.

image

์ดˆ๊ธฐ์—๋Š” ์œ„ ์‚ฌ์ง„ ์ฒ˜๋Ÿผ target์— ํ……ํ…… ๋นˆ ๊ป๋ฐ๊ธฐ๋งŒ ์žˆ๋Š” ์ฑ„๋กœ ์ƒ์„ฑ์ด ๋˜๊ณ  ๋ฐ˜ํ™˜์ด ๋œ๋‹ค.

ํ”„๋ก์‹œ์˜ ํŠน์ง•

  • ํ”„๋ก์‹œ๋Š” ๋‚ด๋ถ€ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‹ค์ œ ํด๋ž˜์Šค๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์† ๋ฐ›์•„์„œ ๋งŒ๋“ค์–ด์ง„๋‹ค.
  • ๋”ฐ๋ผ์„œ ์‹ค์ œ ํด๋ž˜์Šค์™€ ๊ฒ‰ ๋ชจ์–‘์ด ๊ฐ™๋‹ค.
  • ์‚ฌ์šฉํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์ง„์งœ ๊ฐ์ฒด์™€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค(์ด๋ก ์ƒ)
  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์‹ค์ œ ๊ฐ์ฒด์˜ ์ฐธ์กฐ(target)๋ฅผ ๋ณด๊ด€ํ•˜๊ณ  ์žˆ๋‹ค.
  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

ํ”„๋ก์‹œ ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™” Member member = em.getReference(Member.class, "id1"); member.getName(); ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, ํ”„๋ก์‹œ๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— target์„ ์ดˆ๊ธฐํ™” ํ•˜๊ธฐ์œ„ํ•ด ์ดˆ๊ธฐํ™”๋ฅผ ์š”์ฒญํ•œ๋‹ค. ๊ทธ ํ›„ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์กฐํšŒํ•˜์—ฌ ์‹ค์ œ Entity๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  target์€ memberName ๋‚ด์šฉ๋ฌผ์„ ๊ฐ€์ ธ์™€์„œ ์ดˆ๊ธฐํ™” ํ•˜๊ฒŒ๋œ๋‹ค. image

์ค‘์š”ํ•œ ํ”„๋ก์‹œ์˜ ํŠน์ง•

  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์ฒ˜์Œ ์‚ฌ์šฉํ•  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์ดˆ๊ธฐํ™” ๋œ๋‹ค! - ๋‘๋ฒˆ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ ๋””๋น„๋ฅผ ๋”์ด์ƒ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ ๋„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค
  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™” ํ•  ๋•Œ, ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™”๋˜๋ฉด ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด๋‹ค.
  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์›๋ณธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒ์†๋ฐ›๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ํƒ€์ž… ์ฒดํฌ์‹œ ์ฃผ์˜ํ•ด์•ผํ•œ๋‹ค. == ๋น„๊ต ๋Œ€์‹  instance of๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ฐพ๋Š” ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ด๋ฏธ ์žˆ์œผ๋ฉด em.getReference()๋ฅผ ํ˜ธ์ถœํ•ด๋„ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ์ค€์˜์† ์ƒํƒœ์ผ ๋•Œ, ํ”„๋ก์‹œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. (ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๋Š” org.hibernate.LazyInitializationException ์˜ˆ์™ธ๋ฅผ ํ„ฐํŠธ๋ฆฐ๋‹ค. ์ด๋ฌธ์ œ๋Š” ์‹ค์ œ๋กœ ์‹ค๋ฌด์—์„œ ๋งŽ์ด ๋งž๋”ฑ๋œจ๋ฆฌ๊ฒŒ ๋œ๋‹ค. em.close() ํ˜น์€ em.detach()๋ฅผ ํ•˜๊ณ  ํ”„๋ก์‹œ๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋ ค๊ณ ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”๊ฒƒ์ด๋‹ค.
public class JpaMain{
  public class void main(String[] args) {
  	...
    try {
			Member member = new Member();
			member.setUsername("Hello);
			
			em.persist(member);
			em.flush();
			em.clear();
			
			Member findMember = em.find(Member.class, member.getId());
		  System.out.println("FindMember = " + findMember.getUId());
			System.out.println("FindMember = " + findMember.getUsername());
			
			tx.commit();
			}
...

image

์ด๋ ‡๊ฒŒ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ฉด, ์กฐ์ธ ์ฟผ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ํ•ด์™€์„œ member๋งŒ ํ•„์š”ํ•จ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , Team ์ฟผ๋ฆฌ๋„ ๊ฐ™์ด ๊ฐ€์ ธ์˜จ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์ž‡๋‹ค. ํ•˜์ง€๋งŒ em.find() ๋ถ€๋ถ„์„ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ณ ์น˜๋ฉด, select ์ฟผ๋ฆฌ๊ฐ€ ์•ˆ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์ž‡๋‹ค.

	// Member findMember = em.find(Member.class, member.getId());
	Member findMember = em.getReference(Member.class, member.getId());
  // System.out.println("FindMember = " + findMember.getUId());
	// System.out.println("FindMember = " + findMember.getUsername());

์ด๋ ‡๊ฒŒ getID ๋“ฑ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์—†์œผ๋ฉด member, team์˜ ์ฟผ๋ฆฌ๊ฐ€ ํ•˜๋‚˜๋„ ๋‚˜์˜ค์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

image

ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ system.out.println ์˜ ์ฃผ์„์„ ํ’€๊ณ  ์‚ฌ์šฉํ•˜๊ฒŒ๋˜๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ๋ถˆ๋Ÿฌ์™€ ์ง€๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

image

ํ”„๋ก์‹œ๋Š” ์‹ค์ œ ์‚ฌ์šฉ๋˜๋Š” ์‹œ์ ์— ๋””๋น„์— ์ฟผ๋ฆฌ๋ฅผ ์กฐํšŒํ•œ๋‹ค

์ƒ์„ฑ๋œ ํ”„๋ก์‹œ๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•

  • ํ”„๋ก์‹œ ์ธ์Šคํ„ด์Šค์˜ ์ดˆ๊ธฐํ™” ์—ฌ๋ถ€ ํ™•์ธ: PersistenceUil.isLoaded(Object ํ•„์š”ํ•œ entity)
  • ํ”„๋ก์‹œ ํด๋ž˜์Šค ํ™•์ธ ๋ฐฉ๋ฒ•: System.out.println(ํ•„์š”ํ•œ entity.getClass().getName());
  • ํ”„๋ก์‹œ ๊ฐ•์ œ ์ดˆ๊ธฐํ™”: org.hibernate.Hibernate.initialize(ํ•„์š”ํ•œ entity); cf) JPA ํ‘œ์ค€์€ ๊ฐ•์ œ ์ดˆ๊ธฐํ™”๊ฐ€ ์—†๋‹ค. ๊ฐ•์ œ ํ˜ธ์ถœ: member.getName()

์ง€์—ฐ ๋กœ๋”ฉ & ์ฆ‰์‹œ ๋กœ๋”ฉ

  • ์ง€์—ฐ ๋กœ๋”ฉ: ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ๋งคํ•‘ ๋˜์–ด์žˆ๋Š” TEAM๊ณผ MEMBER ์ด ์žˆ์„ ๋•Œ TEAM์ด ๋งŽ์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•˜๋ฉด ์ง€์—ฐ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•œ๋‹ค. Entity์—์„œ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ • ์‹œ fetch๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ์„ธํŒ…ํ•˜๋ฉด ํ”„๋ก์‹œ๋กœ ์ด ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ๋กœ์ง์ด ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ํ”„๋ก์‹œ๊ฐ€ ๋””๋น„์— ์ ‘๊ทผํ•ด์„œ ์ดˆ๊ธฐํ™”๋ฅผ ํ•œ๋‹ค. ํŒ€์„ ๊ฐ€์ ธ์˜ฌ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ ํŒ€์„ ์‚ฌ์šฉํ• ๋•Œ๋‹ค!! team.getName(); ํ• ๋•Œ ์ดˆ๊ธฐํ™”๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.
@Entity
public class Member {
	@Id
	@GenerateValue
	private Long id;
	
	@Column(name = "USERNAME")
	private String name;
	
	@ManyToOne(fetch= FetchType.LAZY) // ์ง€์—ฐ ๋กœ๋”ฉ
	@JoinColumn(name "TEAM_ID")
	private TEAM team;
	}
  • ์ฆ‰์‹œ ๋กœ๋”ฉ: MEMBER์™€ TEAM์ด ๋™์‹œ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ์— ์ฆ‰์‹œ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰์‹œ ๋กœ๋”ฉ์€ EAGER๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์กฐํšŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰์‹œ๋กœ๋”ฉ์€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ํ”„๋ก์‹œ๊ฐ€ ํ•œ๋ฒˆ์— ์ฆ‰์‹œ ์ดˆ๊ธฐํ™” ๋œ๋‹ค.
@Entity
public class Member {
	@Id
	@GenerateValue
	private Long id;
	
	@Column(name = "USERNAME")
	private String name;
	
	@ManyToOne(fetch= FetchType.EAGER) // ์ฆ‰์‹œ ๋กœ๋”ฉ
	@JoinColumn(name "TEAM_ID")
	private TEAM team;
	}

ํ”„๋ก์‹œ์™€ ์ฆ‰์‹œ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ• ์ 

  • ๊ฐ€๊ธ‰์  ์ง€์—ฐ ๋กœ๋”ฉ๋งŒ ์‚ฌ์šฉํ•˜๊ธฐ!!(ํŠนํžˆ ์‹ค๋ฌด์—์„œ๋Š” ๋”๋”์šฑ์ด ๊ทธ๋ ‡๋‹ค)
  • ์ฆ‰์‹œ ๋กœ๋”ฉ์„ ์ ์šฉํ•˜๋ฉด ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ SQL์ด ๋ฐœ์ƒ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ์ฆ‰์‹œ ๋กœ๋”ฉ์€ JPQL์—์„œ N+1 ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚จ๋‹ค. ex) sql์—์„œ member์„ ํƒ์ƒ‰ํ•˜๋‹ค๊ฐ€ TEAM์ด๋ผ๋Š” ์†์„ฑ์ด ์žˆ๊ณ , eagerํƒ€์ž…์œผ๋กœ ๋˜์–ด์žˆ์œผ๋ฉด TEAM๋„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ค‘๋ณต๋˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋งŽ์ด ์ƒ์„ฑ๋˜๊ฒŒ ๋œ๋‹ค. ์ตœ์ดˆ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ธ๋Š”๋ฐ ์ถ”๊ฐ€์ ์œผ๋กœ ๋˜‘๊ฐ™์€ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ์œ„์— ๋งํ•œ N+1์ฟผ๋ฆฌ๋ผ๊ณ  ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ 1์ด ์ตœ์ดˆ ์ฟผ๋ฆฌ, n์ด ์ค‘๋ณต ์ฟผ๋ฆฌ์ด๋‹ค. cf) ์ฆ‰์‹œ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€๋งŒ N+1๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ชจ๋‘ ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ๊น๋‹ค์Œ์—, jpql์—์„œ fetchJoin์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Š” join๋˜์–ด์žˆ๋Š” ๋ชจ๋“  ์ฟผ๋ฆฌ๋ฅผ 1๋ฒˆ๋งŒ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.
  • @ManyToOne, @OneToOne์€ ๊ธฐ๋ณธ์ด ์ฆ‰์‹œ ๋กœ๋”ฉ์ด๊ธฐ๋•Œ๋ฌธ์— LAZY๋กœ ์„ค์ •ํ•ด์ฃผ๊ธฐ!!!
  • @OneToMany, @ManyToMany๋Š” ๊ธฐ๋ณธ์ด ์ง€์—ฐ ๋กœ๋”ฉ์ด๋‹ค.

์ง€์—ฐ๋กœ๋”ฉ์„ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•! ์ด๊ฒƒ์€ ์ด๋ก ์ ์ธ ๊ฒƒ์ด๊ณ , ์‹ค๋ฌด์—์„œ๋Š” ๋ชจ๋‘ ๋‹ค ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

  • Member์™€ Team์ด ์ž์ฃผ ์‚ฌ์šฉ๋˜๋ฉด ์ฆ‰์‹œ ๋กœ๋”ฉ
  • Member์™€ order๋Š” ๊ฐ€๋” ์‚ฌ์šฉ๋˜๋ฉด ์ง€์—ฐ๋กœ๋”ฉ
  • order์™€ product๋Š” ์ž์ฃผ ์‚ฌ์šฉ๋˜๋ฉด ์ฆ‰์‹œ๋กœ๋”ฉ image

์ง€์—ฐ ๋กœ๋”ฉ์„ ์‹ค๋ฌด์—์„œ ํ™œ์šฉํ• ๋•Œ!!

  • ๋ชจ๋“  ์—ฐ๊ด€๊ด€๊ณ„์— ์ง€์—ฐ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•ด๋ผ!
  • ์‹ค๋ฌด์—์„œ ์ฆ‰์‹œ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ!
  • jpql fetch ์กฐ์ธ์ด๋‚˜, ์—”ํ‹ฐํ‹ฐ ๊ทธ๋ž˜ํ”„ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ(๋’ค์—์„œ ์„ค๋ช…)
  • ์ฆ‰์‹œ ๋กœ๋”ฉ์€ ์ƒ์ƒํ•˜์ง€ ๋ชปํ•œ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜์˜จ๋‹ค.

์˜์†์„ฑ ์ „์ด:CASCADE

cf) ์ง€์—ฐ ๋กœ๋”ฉ, ์ฆ‰์‹œ๋กœ๋”ฉ๊ณผ ์ „ํ˜€ ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค.

  • ํŠน์ • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์† ์ƒํƒœ๋กœ ๋งŒ๋“ค ๋•Œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์˜์† ์ƒํƒœ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ex) ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์ €์žฅํ•˜๊ณ  ์‹ถ์„ ๋•Œ์ด๋‹ค. == ๋ถ€๋ชจ๋ฅผ ์ €์žฅํ• ๋•Œ, ์ž์‹๋„ ๋ชจ๋‘ persist๋กœ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค
  • ์˜์†์„ฑ ์ „์ด(์ €์žฅ) : @OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
@Entity
public class Parent {
	@Id
	@GeneratedValue
	private Long id;
	private String name;
	@OneToMany(mappedBy="parent", cascade = CascadeType.ALL)
	private List<Child> childList = new ArrayList<>();
	
	public void addChild(Child child){
		childList.add(child);
		child.setParent(this);
	}
	
	//getter setter
	... 
@Entity
public class Child{
	@Id
	@GeneratedValue
	private Long id;
	private String name;
	
	@ManyToOne
	@JoinColumn(name = "parent_id")
	private Parent parent;
	// getter setter
	...
//JpaMain
public class JpaMain{
 public static void main(String[] args){
 	EntityManagerFactory emf = Persistence.createEntityManageFactory("hello');
	EntityManager em = emf.createEntityManager();
	
	EntityTransaction tx - em.getTransaction();
	
	try{
		Child child1 = new Child();
		Child child2 = new Child();
		
		Parant parent = new Parent();
		parent.addChild(child1);
		parent.addChild(child2);
		
		//  ์ด๋•Œ persist๊ฐ€ 3๋ฒˆ์ด๋‚˜ ํ•„์š”ํ•˜๋‹ค. 
		em.persist(parent);
		em.persist(child1);
		em.persist(child2);
    // cascade๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
		em.persist(parent);
		
		tx.commmit();
	}
	...

์šฐ๋ฆฌ๋Š” parent๊ฐ€ persist ๊ฐ€ ๋˜์—ˆ์„ ๋•Œ child๋„ ๊ตณ์ด persist ์•ˆํ•ด์ค˜๋„ ์ €์ ˆ๋กœ ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค! ์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์˜์†์„ฑ ์ „์ด(CASCADE)์ด๋‹ค.

์˜์†์„ฑ ์ „์ด: CASCADE - ์ฃผ์˜!

  • ์˜์†์„ฑ ์ „์ด๋Š” ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ๊ณผ ์•„๋ฌด ๊ด€๋ จ์ด ์—†๋‹ค.
  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์†ํ™”ํ•  ๋•Œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์˜์†ํ™”ํ•˜๋Š” ํŽธ๋ฆฌํ•จ์„ ์ œ๊ณตํ•  ๋ฟ์ด๋‹ค.
  • ์ผ๋Œ€๋‹ค์ผ๋•Œ ํ•ญ์ƒ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ๋ถ€๋ชจ๊ฐ€ ๋ชจ๋‘ ์ž์‹๋“ค์„ ๊ด€๋ฆฌํ• ๋•Œ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค. (๋‹จ์ผ ์†Œ์œ ์ž์ผ๋•Œ)
  • ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ํŒŒ์ผ์—์„œ ์ž๋…€์˜ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ด€๋ฆฌํ• ๋•Œ, ์ฆ‰ ์—ฌ๋Ÿฌ ๋ถ€๋ชจ๊ฐ€ ๊ฐ™์€ ์ž์‹์„ ๊ด€๋ฆฌํ• ๋•Œ๋Š” ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

CASCADE์˜ ์ข…๋ฅ˜

  • ALL: ํ•ญ์ƒ ๊ฐ™์ด ์ €์žฅ๋˜์–ด์•ผ ํ• ๋•Œ ์‚ฌ์šฉ
  • PERSIST: ๊ทธ๋ƒฅ ์ €์žฅํ• ๋•Œ ์˜์†์šฉ์œผ๋กœ ์‚ฌ์šฉ
  • REMOVE: ์‚ญ์ œ
  • MERGE: ๋ณ‘ํ•ฉ
  • REFRESH: REFRESH
  • DETACH: DETACH

๊ณ ์•„ ๊ฐ์ฒด

  • ๊ณ ์•„ ๊ฐ์ฒด ์ œ๊ฑฐ: ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ๋Š์–ด์ง„ ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ž๋™์œผ๋กœ ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • orphanRemoval = true
  • Parent parent1 = em.find(Parent.class, id); parent1.getChildren().remove(0); // ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ปฌ๋ ‰์…˜์—์„œ ์ œ๊ฑฐ
  • DELETE FROM CHILD WHERE ID=?

๊ณ ์•„ ๊ฐ์ฒด ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ 

  • ์ฐธ์กฐ๊ฐ€ ์ œ๊ฑฐ๋œ ์—”ํ‹ฐํ‹ฐ๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š” ๊ณ ์•„ ๊ฐ์ฒด๋กœ ๋ณด๊ณ  ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ์ฐธ์กฐํ•˜๋Š” ๊ณณ์ด ํ•˜๋‚˜์ผ ๋•Œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค!!
  • ํŠน์ • ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ฐœ์ธ ์†Œ์œ ํ•  ๋•Œ ์‚ฌ์šฉ
  • @OneToOne, @OneToMany๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค
  • cf) ๊ฐœ๋…์ ์œผ๋กœ ๋ถ€๋ชจ๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์ž์‹์€ ๊ณ ์•„๊ฐ€ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๊ณ ์•„ ๊ฐ์ฒด ์ œ๊ฑฐ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™” ํ•˜๋ฉด ๋ถ€๋ชจ๋ฅผ ์ œ๊ฑฐํ• ๋•Œ ์ž์‹๋„ ํ•จ๊ป˜ ์ œ๊ฑฐ๋œ๋‹ค. ์ด๊ฒƒ์€ CascadeType.REMOVE์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค.

์˜์†์„ฑ ์ „์ด+๊ณ ์•„ ๊ฐ์ฒด, ์ƒ๋ช…์ฃผ๊ธฐ

  • CascadeType.ALL + orphanRemovel=true
  • ์Šค์Šค๋กœ ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ๋Š” em.persist()๋กœ ์˜์†ํ™”, em.remove()๋กœ ์ œ๊ฑฐํ•œ๋‹ค.
  • ๋‘ ์˜ต์…˜์„ ๋ชจ๋‘ ํ™œ์„ฑํ™” ํ•˜๋ฉด ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ†ตํ•ด์„œ ์ž์‹์˜ ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋„๋งค์ธ ์ฃผ๋„ ์„ค๊ณ„(DDD)์˜ Aggregate Root ๊ฐœ๋…์„ ์ˆ˜ํ˜„ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค

๊ธฐ๋ณธ๊ฐ’ ์ž…

JPA๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์—”ํ‹ฐํ‹ฐ ํƒ€์ž…๊ณผ ๊ฐ’ ํƒ€์ž…์œผ๋กœ ํฌ๊ฒŒ 2๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค.

  • ์—”ํ‹ฐํ‹ฐ ํƒ€์ž…์ด๋ž€

    • @Entity๋กœ ์ •์˜ํ•˜๋Š” ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ๋งํ•œ๋‹ค.
    • ์ด๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ•ด๋„ ์‹๋ณ„์ž(pk)๋กœ ์ง€์†ํ•ด์„œ ์ถ”์ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.
    • ex) ํšŒ์› ์—”ํ‹ฐํ‹ฐ์˜ ํ‚ค๋‚˜ ๋‚˜์ด ๊ฐ’์„ ๋‹ค ๋ณ€๊ฒฝํ•ด๋„ ์ด ๋ฐ์ดํ„ฐ๊ฐ€ ํŠน์ • ์œ ์ €์˜ ๋ฐ์ดํ„ฐ๋ผ๋Š” ๊ฒƒ์„ ์ธ์‹ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๊ฐ’ ํƒ€์ž…์ด๋ž€

    • int, Integer, String์ฒ˜๋Ÿผ ๋‹จ์ˆœํžˆ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ž๋ฐ” ๊ธฐ๋ณธ ํƒ€์ž…์ด๋‚˜ ๊ฐ์ฒด๋ฅผ ๋งํ•œ๋‹ค.
    • ์ด๋Š” ์‹๋ณ„์ž๊ฐ€ ์—†๊ณ  ๊ฐ’๋งŒ ์žˆ์œผ๋ฏ€๋กœ ๋ณ€๊ฒฝ์‹œ ์ถ”์ ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ex) ์ˆซ์ž 100์„ 200์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์™„์ „ํžˆ ๋‹ค๋ฅธ ๊ฐ’์„ ๋Œ€์ฒด๋œ๋‹ค.

๊ฐ’ํƒ€์ž… ๋ถ„๋ฅ˜(3๊ฐ€์ง€)

  • ๊ธฐ๋ณธ๊ฐ’ ํƒ€์ž…
    • ์ž๋ฐ” ๊ธฐ๋ณธ ํƒ€์ž…(int, double)
    • ๋ž˜ํผ ํด๋ž˜์Šค(Integer, Long)
    • String
  • **์ž„๋ฒ ์ด๋“œ ํƒ€์ž…(embedded type, ๋ณตํ•ฉ ๊ฐ’ ํƒ€์ž…)
  • ์ปฌ๋ ‰์…˜ ๊ฐ’ ํƒ€์ž…

๊ธฐ๋ณธ๊ฐ’ ํƒ€์ž…

  • ex) String name, int age
  • ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์—”ํ‹ฐํ‹ฐ์— ์˜์กดํ•œ๋‹ค.
    • ex) ํšŒ์›์„ ์‚ญ์ œํ•˜๋ฉด ์ด๋ฆ„, ๋‚˜์ด ํ•„๋“œ๋„ ํ•จ๊ป˜ ์‚ญ์ œ๋œ๋‹ค.
  • ๊ฐ’ ํƒ€์ž…์€ ๊ณต์œ ํ•˜๋ฉด ์ ˆ๋Œ€ ์•ˆ๋œ๋‹ค.
    • ex) ํšŒ์› ์ด๋ฆ„ ๋ณ€๊ฒฝ ์‹œ ๋‹ค๋ฅธ ํšŒ์›์˜ ์ด๋ฆ„๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝ๋˜๋ฉด ์•ˆ๋œ๋‹ค. == sideEffect cf) ์ž๋ฐ”์˜ ๊ธฐ๋ณธ ํƒ€์ž…์€ ์ ˆ๋Œ€ ๊ณต์œ ๋˜์ง€ ์•Š๋Š”๋‹ค.
      • int, double ๊ฐ™์€ ๊ธฐ๋ณธ ํƒ€์ž…(primitive type)์€ ์ ˆ๋Œ€ ๊ณต์œ ๋˜์ง€ ์•Š๋Š”๋‹ค.
      • ๊ธฐ๋ณธ ํƒ€์ž…์€ ํ•ญ์ƒ ๊ฐ’์„ ๋ณต์‚ฌํ•œ๋‹ค.
      • Integer๊ฐ™์€ ๋ž˜ํผ ํด๋ž˜์Šค๋‚˜ String ๊ฐ™์€ ํ‹€์ˆ˜ํ•œ ํด๋ž˜์Šค๋Š” ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด์ด์ง€๋งŒ ๋ณ€๊ฒฝ์€ ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ž„๋ฒ ๋””๋“œ ํƒ€์ž…(๋ณตํ•ฉ ๊ฐ’ ํƒ€์ž…)

์ž„๋ฒ ๋””๋“œ ํƒ€์ž…

  • ์ƒˆ๋กœ์šด ๊ฐ’ ํƒ€์ž…์„ ์ง์ ‘ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค
  • JPA๋Š” ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…(embedded type)์ด๋ผ๊ณ  ํ•œ๋‹ค.
  • ์ฃผ๋กœ ๊ธฐ๋ณธ ๊ฐ’ ํƒ€์ž…์„ ๋ชจ์•„์„œ ๋งŒ๋“ค์–ด์„œ ๋ณตํ•ฉ ๊ฐ’ ํƒ€์ž…์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.
  • ์ด๋Š” int, String๊ณผ ๊ฐ™์€ ๊ฐ’ ํƒ€์ž…์ด๋ฏ€๋กœ ์ถ”์ ์ด ์•ˆ๋œ๋‹ค. ๋ณ€๊ฒฝํ•˜๋ฉด ๋!

์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์˜ˆ๋ฅผ ํ•œ๋ฒˆ ๋“ค์–ด๋ณด์ž. ์šฐ๋ฆฌ๋Š” ํšŒ์› ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒ์„ฑํ• ๋•Œ, ์ด๋ฆ„, ๊ทผ๋ฌด ์‹œ์ž‘์ผ, ๊ทผ๋ฌด ์ข…๋ฃŒ์ผ, ์ฃผ์†Œ ๋„์‹œ, ์ฃผ์†Œ ๋ฒˆ์ง€, ์ฃผ์†Œ ์šฐํŽธ๋ฒˆํ˜ธ๋ฅผ ๊ฐ€์ง„๋‹ค. == id, name, startDate, endDate, city, street, zipcode ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์—๋Š” ๋น„์Šทํ•œ ์†์„ฑ์ธ ๊ฒƒ๋“ค์ด ์žˆ๋‹ค. startDate์™€ endDate๋Š” ๊ธฐ๊ฐ„์— ๊ด€๋ จ๋œ ๊ฒƒ์ด๊ณ , city, street, zipcode๋Š” ์ง‘ ์ฃผ์†Œ์™€ ๊ด€๋ จ๋˜์–ด์žˆ๋‹ค. ์ด๋ฅผ ํ•˜๋‚˜์˜ ๊ด€๋ จ๋œ ๊ฒƒ์œผ๋กœ ๋ฌถ๊ณ  ์‹ถ์„ ๋•Œ ์šฐ๋ฆฌ๋Š” ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ๋‹ค. startPeriod์™€ endPeriod๋Š” workPeriod๋กœ, city, street, zipcode๋Š” homeAddress๋กœ ๋ฌถ๊ณ ์‹ถ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด member์˜ ์†์„ฑ์ด ๋งค์šฐ ๊ฐ„๋‹จํ•ด์ง„๋‹ค. image image

์ž„๋ฒ ๋””๋“œ ํƒ€์ž… ์‚ฌ์šฉ๋ฒ•

  1. @Embeddable: ๊ฐ’ ํƒ€์ž…์„ ์ •์˜ํ•˜๋Š” ๊ณณ์— ํ‘œ์‹œํ•œ๋‹ค.
  2. @Embedded: ๊ฐ’ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์— ํ‘œ์‹œํ•œ๋‹ค.
  3. ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋Š” ํ•„์ˆ˜์ด๋‹ค!

์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์˜ ์žฅ์ 

  • ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‘์ง‘๋„๊ฐ€ ๋†’๋‹ค.
  • Period.isWork()์ฒ˜๋Ÿผ ํ•ด๋‹น ๊ฐ’ ํƒ€์ž…๋งŒ ์‚ฌ์šฉํ•˜๋Š” ์˜๋ฏธ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. == ๊ฐ์ฒด ์ง€ํ–ฅ์— ์ข‹์Œ!!
  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ํฌํ•จํ•œ ๋ชจ๋“  ๊ฐ’ ํƒ€์ž…์€, ๊ฐ’ ํƒ€์ž…์„ ์†Œ์œ ํ•œ ์—”ํ‹ฐํ‹ฐ์— ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์˜์กดํ•œ๋‹ค.
@Entity
public class Member {
	@Id
	@GeneratedValue
	@Column(name="MEMBER_ID")
	private Long id;
	
	@Column(name = "USERNAME")
	private String username;
	
	//๊ธฐ๊ฐ„ period
	@Embedded
	private Period period;
	
	//์ฃผ์†Œ
	@Embedded
	private Address address;
	
	//getter setter 
	...
}
@Embeddable
public class Period {
	private LocalDateTime startDate;
	private LocalDateTime endDate;
	
	public Period() {} // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž
	//getter setter
	...
}
@Embeddable
public class Address {
	private String city;
	private String street;
	private String zipcode;
	
	public Address() {} // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž
	
	public Address(String city, String street, String zipcode){
		this.city = city;
		this.street = street;
		this.zipcode = zipcode;
	}
	
	//getter setter 
	...
}
public class JpaMain {
	public static void main(String[] args) {
		//emf, em
		...
		try{
			Member member = new Memeber();
			member.setUsername("Hello");
			member.setHomeAddress(new Address("city", "street", "zipcode");
			member.setWordPeriod(new Period());
			...
		}
		...
	}
}

์ž„๋ฒ ๋””๋“œ ํƒ€์ž…๊ณผ ํ…Œ์ด๋ธ” ๋งคํ•‘

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์€ ์—”ํ‹ฐํ‹ฐ์˜ ๊ฐ’์ผ ๋ฟ์ด๋‹ค.
  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „๊ณผ ํ›„์— ๋งคํ•‘ํ•˜๋Š” ํ…Œ์ด๋ธ”์€ ๊ฐ™๋‹ค.
  • ๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ”์„ ์•„์ฃผ ์„ธ๋ฐ€ํ•˜๊ฒŒ(find-grained) ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์ž˜ ์„ค๊ณ„ํ•œ ORM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋งคํ•‘ํ•œ ํ…Œ์ด๋ธ”์˜ ์ˆ˜๋ณด๋‹ค ํด๋ž˜์Šค์˜ ์ˆ˜๊ฐ€ ๋” ๋งŽ๋‹ค.
  • ์ด๋ฅผ ์“ฐ๋ฉด ์šฉ์–ด, ์ฝ”๋“œ, ๋„๋ฉ”์ธ์— ์–ธ์–ด๋“ค์„ ๊ณตํ†ต์œผ๋กœ ๊ณต์œ ํ•˜๋ฉด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
  • ์—”ํ‹ฐํ‹ฐ ํ•˜์œ„์— ๊ฐ’ ํƒ€์ž…(ADDRESS)์ด ๋“ค์–ด์˜ฌํ…๋ฐ ์ด ํ•˜์œ„์— ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋“ค์–ด์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

AttributeOverride: ์†์„ฑ ์žฌ์ •์˜

  • ๋งŒ์•ฝ์— ํ•œ ์—”ํ‹ฐํ‹ฐ์—์„œ ๊ฐ™์€ ๊ฐ’ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
	@Embedded
	private Address homeAddress;
	@Embedded
	private Address workAddress;
  • ์ด๋•Œ ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด AttributeOverride์ด๋‹ค.
  • ์—ฌ๋Ÿฌ๊ฐœ๋ฉด AttributeOverrides, ํ•˜๋‚˜๋ฉด @AttributeOverride๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ปฌ๋Ÿฌ ๋ช… ์†์„ฑ์„ ์žฌ์ •์˜ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

์ž„๋ฒ ๋””๋“œ ํƒ€์ž…๊ณผ null

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์˜ ๊ฐ’์ด null์ด๋ฉด ๋งคํ•‘ํ•œ ์ปฌ๋Ÿผ ๊ฐ’์€ ๋ชจ๋‘ null์ด ๋œ๋‹ค.

๊ฐ’ ํƒ€์ž…๊ณผ ๋ถˆ๋ณ€ ๊ฐ์ฒด = ๊ฐ’ ํƒ€์ž…์€ ๋ฌด์กฐ๊ฑด ๋ถˆ๋ณ€์œผ๋กœ ๋งŒ๋“ค์ž!!!

  • ๊ฐ’ ํƒ€์ž…์€ ๋ณต์žกํ•œ ๊ฐ์ฒด ์„ธ์ƒ์„ ์กฐ๊ธˆ์ด๋ผ๋„ ๋‹จ์ˆœํ™”ํ•˜๋ ค๊ณ  ๋งŒ๋“  ๊ฐœ๋…์ด๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ’ ํƒ€์ž…์€ ๋‹จ์ˆœํ•˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์€ ๋ถ€๋‹ด์Šค๋Ÿฌ์›Œ ํ•˜๋ฉด์„œ ๊ฐ’์„ ๋ณต์‚ฌํ•  ๋•Œ๋Š” ํฌ๊ฒŒ ์‹ ๊ฒฝ์„ ์•ˆ์“ฐ๋ฉด์„œ ์ฝ”๋”ฉ์„ ํ•˜๊ฒŒ ๋œ๋‹ค. - ์ด๋Š” ๊ฐ’ ํƒ€์ž…์ด ์ž๋ฐ” ์„ธ์ƒ์—์„œ๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ์„ค๊ณ„๋˜์–ด ์žˆ์–ด์„œ ๊ดœ์ฐฎ์€ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ’ ํƒ€์ž…์„ ๋ณต์‚ฌํ•  ๋•Œ ํ•ญ์ƒ ์•ˆ์ „ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

๊ฐ’ ํƒ€์ž… ๊ณต์œ  ์ฐธ์กฐ

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž… ๊ฐ™์€ ๊ฐ’ ํƒ€์ž…์„ ์—ฌ๋Ÿฌ ์—”ํ‹ฐํ‹ฐ์—์„œ ๊ณต์œ ํ•˜๋ฉด ๋งค์šฐ ์œ„ํ—˜ํ•˜๋‹ค.
  • ๋ถ€์ž‘์šฉ(Side Effect)๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด member1๋งŒ ๊ฑฐ์ฃผ์ง€๋ฅผ ๋ฐ”๊พธ๋ ค๊ณ  setcity๋ฅผ ํ•˜๋ ค๊ณ  ํ•˜๋ฉด, sql์€ insert ์ฟผ๋ฆฌ๋ฅผ 2๋ฒˆ ๋ณด๋‚ด์„œ member2์˜ ๋„์‹œ๋„ newCity๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฐ๋‹ค.
try {
	Address address = new Address("city", "street", "10000");
	
	Member member = new Member();
	member.setUsername("member1");
	member.setHomeAddress(address);
	em.persist(member);

	Member member2 = new Member();
	member2.setUsername("member2");
	member2.setHomeAddress(address);
	em.persist(member2);
	
	member.getHomeAddress().setCity("newCity");	

๊ฐ’ ํƒ€์ž… ๋ณต์‚ฌ

  • ๊ฐ’ ํƒ€์ž…์˜ ์‹ค์ œ ์ธ์Šคํ„ด์Šค์ธ ๊ฐ’์„ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์œ„ํ—˜ํ•˜๋‹ค.
  • ๋”ฐ๋ผ์„œ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ๊ฐ’์„ ๊ณต์œ  ํ•˜๋Š” ๊ฒƒ ๋Œ€์‹  ์ธ์Šคํ„ด์Šค ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ๋œ๋‹ค.
try {
	Address address = new Address("city", "street", "10000");
	
	Member member = new Member();
	member.setUsername("member1");
	member.setHomeAddress(address);
	em.persist(member);

	Address copyAddresss = new Address(address.getCity(), address.getStreet(), address.getZipcode());

	Member member2 = new Member();
	member2.setUsername("member2");
	member2.setHomeAddress(copyAddress);
	em.persist(member2);
	
	member.getHomeAddress().setCity("newCity");	

๊ฐ์ฒด ํƒ€์ž…์˜ ํ•œ๊ณ„

  • ํ•ญ์ƒ ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๊ณต์œ  ์ฐธ์กฐ(์œ„์™€ ๊ฐ™์€ ์ƒํ™ฉ)๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ๋ถ€์ž‘์šฉ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฌธ์ œ๋Š” ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์ฒ˜๋Ÿผ ์ง์ ‘ ์ •์˜ํ•œ ๊ฐ’ ํƒ€์ž…์€ ์ž๋ฐ”์˜ ๊ธฐ๋ณธ ํƒ€์ž…์ด ์•„๋‹ˆ๋ผ ๊ฐ์ฒด ํƒ€์ž…์ด๋‹ค.
  • ์ž๋ฐ” ๊ธฐ๋ณธ ํƒ€์ž…์— ๊ฐ’์„ ๋Œ€์ž…ํ•˜๋ฉด ๊ฐ’์„ ๋ณต์‚ฌํ•œ๋‹ค.
  • ๊ฐ์ฒด ํƒ€์ž…์€ ์ฐธ์กฐ ๊ฐ’์„ ์ง์ ‘ ๋Œ€์ž…ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค.
  • ๊ฐ์ฒด์˜ ๊ณต์œ  ์ฐธ์กฐ๋Š” ํ”ผํ•  ์ˆ˜ ์—†๋‹ค.
  • ๊ฐ์ฒด ๊ณต์œ ๋Š” ์„œ๋กœ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค(์ฃผ์†Œ๊ฐ’)์„ ๊ณต์œ ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์ด ๋ณ€๊ฒฝ์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ถˆ๋ณ€ ๊ฐ์ฒด

  • ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ์ฒด ํƒ€์ž…์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ค์–ด ๋ถ€์ž‘์šฉ์„ ์›์ฒœ ์ฐจ๋‹จ์‹œ์ผœ๋ฒ„๋ ค์•ผ ํ•œ๋‹ค.
  • ๊ฐ’ ํƒ€์ž…์€ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ์„ค๊ณ„ํ•ด์•ผํ•œ๋‹ค.
  • ์ƒ์„ฑ์ž๋กœ๋งŒ ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ  ์ˆ˜์ •์ž(Setter)๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์œผ๋ฉด ๋œ๋‹ค.
  • ์ฐธ๊ณ ๋กœ, Integer, String์€ ์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ๋ถˆ๋ณ€ ๊ฐ์ฒด์ด๋‹ค. **๋ถˆ๋ณ€์ด๋ผ๋Š” ์ž‘์€ ์ œ์•ฝ์œผ๋กœ ๋ถ€์ž‘์šฉ์ด๋ผ๋Š” ํฐ ์žฌ์•™์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด setter๊ฐ€ ์—†๋‹ค๋ฉด ๊ฐ’์€ ์–ด๋–ป๊ฒŒ ๋ฐ”๊ฟ€๊ฒƒ์ธ๊ฐ€?

try {
	Address address = new Address("city", "street", "10000");
	
	Member member = new Member();
	member.setUsername("member1");
	member.setHomeAddress(address);
	em.persist(member);

	// address๋ฅผ ํ†ต์งธ๋กœ ๊ฐˆ์•„๋ผ์›Œ์•ผํ•œ๋‹ค. 
	Address newAddresss = new Address("newCity", address.getStreet(), address.getZipcode()); 
	member.setHomeASddress(newAddress);
}
	

๊ฐ’ ํƒ€์ž…์˜ ๋น„๊ต

  • ๊ฐ’ ํƒ€์ž…: ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹ฌ๋ผ๋„ ๊ทธ ์•ˆ์— ๊ฐ’์ด ๊ฐ™์€๋ฉด ๊ฐ™์€ ๊ฒƒ์œผ๋กœ ๋ด์•ผ ํ•œ๋‹ค.
  • ํ•˜์ง€๋งŒ ๊ฐ์ฒด๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹ค๋ฅด๋ฉด ๊ทธ ์•ˆ์— ๊ฐ’์ด ๊ฐ™์•„๋„ ๋‹ค๋ฅธ๊ฒƒ์œผ๋กœ ๋ณธ๋‹ค.
  • ๋™์ผ์„ฑ(identity)์˜ ๋น„๊ต: ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ๊ฐ’์„ ๋น„๊ตํ•œ๋‹ค. == ์‚ฌ์šฉ.
  • ๋™๋“ฑ์„ฑ()์˜ ๋น„๊ต: ์ธ์Šคํ„ด์Šค์˜ ๊ฐ’์„ ๋น„๊ตํ•œ๋‹ค. equals() ์‚ฌ์šฉ
  • ๊ฐ’ ํƒ€์ž…์€ a.equals(b)๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋™๋“ฑ์„ฑ ๋น„๊ต๋ฅผ ํ•ด์•ผํ•œ๋‹ค.
  • ๊ฐ’ ํƒ€์ž…์˜ equals() ๋ฉ”์†Œ๋“œ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์žฌ์ •์˜(์ฃผ๋กœ ๋ชจ๋“  ํ•„๋“œ ์‚ฌ์šฉ)

๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜

  • ๊ฐ’ ํƒ€์ž…์„ ์ปฌ๋ ‰์…˜์— ๋‹ด์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ธฐ์กด์— ์ผ๋Œ€๋‹ค ๋“ฑ์„ ๋นŒ๋“œํ•  ๋•Œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ปฌ๋ ‰์…˜์œผ๋กœ ์‚ฌ์šฉํ•˜์˜€๋‹ค. ํ•˜์ง€๋งŒ ์ปฌ๋ ‰์…˜์— ๊ฐ’ ํƒ€์ž„์„ ๋‹ด์•„์„œ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ๊ฐ’ ํƒ€์ž…์„ ์ปฌ๋ ‰์…˜์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๋•Œ, ์—ฌ๊ธฐ์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ปฌ๋ ‰์…˜์„ ํ…Œ์ด๋ธ” ์•ˆ์— ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๊ฐ€ ์—†๊ณ  ๊ฐ’๋งŒ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ํŠน์„ฑ์ด๋‹ค.

๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜ ์ ์šฉ ๋ฐฉ๋ฒ•

  • ๊ฐ’ ํƒ€์ž…์„ ํ•˜๋‚˜ ์ด์ƒ ์ €์žฅํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
  • @ElemnetCollection, @CollectionTable์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ปฌ๋ ‰์…˜์„ ๊ฐ™์€ ๋ฐ์ด๋ธ”์— ์ €์žฅํ•  ์ˆ˜ ์—†๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ปฌ๋ ‰์…˜์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์ด ํ•„์š”ํ•˜๋‹ค.
  • cf) ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜์€ ์˜์†์„ฑ ์ „์ด(Cascade) + ๊ณ ์•„ ๊ฐ์ฒด ์ œ๊ฑฐ ๊ธฐ๋Šฅ์„ ํ•„์ˆ˜๋กœ ๊ฐ€์ง„๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. image
@Entity
public class Member {
	...
	@Embedded
	private Address homeAddress;
	
	@ElementCollection
	@CollectionTable(name = "FAVORIT_FOOD", joinColumns = @JoinColumn(name = "MEMBER_ID"))
	private Set<String> favoriteFoods = new HashSet<>();
	
	@ElementCollection
	@CollectionTable(name = "ADDRESS" , joinColumns = @JoinColumn(name = "MEMBER_ID"))
	// address ๊ฐ’ ํƒ€์ž…์„ ์—ฌ๋Ÿฌ๊ฐœ ์ €์žฅ
	private List<Address> addressHistory = new ArrayList<>();
	...
  • ๊ฐ’ ํƒ€์ž… ์ €์žฅ ์˜ˆ์ œ
public class JpaMain {
	public static void main(String[] args) {
		...
		try{
			Member member = new Member();
			member.setUsername("member1");
			member.setAddress(new Address("HomeCity", "street", "10000"));
			
			member.getFavoritFoods().add("์น˜ํ‚จ");
			member.getFavoritFoods().add("ํ”ผ์ž");
			member.getFavoritFoods().add("์กฑ๋ฐœ");

			member.getAddressHistory().add(new Address("old1", "street", "10000"));
			member.getAddressHistory().add(new Address("old2", "street", "10000"));
}}}
  • ๊ฐ’ ํƒ€์ž… ์กฐํšŒ + ๊ฐ’ ํƒ€์ž… ์ˆ˜์ • ๋ฐฉ๋ฒ• + ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜๋„ ์ง€์—ฐ ๋กœ๋”ฉ ์ „๋žต ์‚ฌ์šฉ
public class JpaMain {
	public static void main(String[] args) {
		...
		try{
			// ์ด์ „ ์ฝ”๋“œ๋“ค
			...
			Member findMember = em.find(Member.class, member.getId()); // ์ปฌ๋ ‰์…˜์€ ์ง€์—ฐ๋กœ๋”ฉ, address ๋Š” 
			List<Address> addressHistory = findMember.getAddressHistory();
			for(Address address : addressHistory) {
				System.out.println("address = " + address. getCity());
			}
			
			Set<String> favoriteFoods = findMember.getFavoritFoods();
			for (String favoriteFood : favoriteFoods) {
				System.out.println("favoriteFood = " + favoriteFood);
			}
			
			// ๊ฐ’ ํƒ€์ž… ๋‚ด์šฉ ์ˆ˜์ • 
			// findMember.getHomeAddress().setCity("newcity"); -> ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ• = ์‚ฌ์ด๋“œ ์ดํŒฉํŠธ
			Address a = findMember = em.find(Member.class, member.getId());
			// ํ†ต์งธ๋กœ ๊ฐˆ์•„๋ผ์šฐ๊ธฐ!! = ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•
			findMember.setHomeAddress(new Address("newCity", "a.getStreet(), a.getZipcode()));
			
			// ์น˜ํ‚จ์„ ํ•œ์‹์œผ๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด? foodFavorit์€ set<String>์ด๊ธฐ ๋•Œ๋ฌธ์— ์• ์ดˆ์— ๊ฐ’ํƒ€์ž…์ด๋ฏ€๋กœ ๊ฐˆ์•„๋‚„ ์ˆ˜๊ฐ€ ์—†๋‹ค.
			findMember.getFavoriteFoods().remove("์น˜ํ‚จ");
			findMember.getFavoriteFoods().add("ํ•œ์‹");
			// ์ด๋Ÿฐ์‹์œผ๋กœ ์•„์˜ˆ ์—†์• ์คฌ๋‹ค๊ฐ€ ๋”ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค. 
			
			// ์ฃผ์†Œ๋ฅผ ๋ฐ”๊ฟ€ ๊ฒฝ์šฐ
			findMember.getAddressHistory().remove(new Address("old1", "street", "10000"));
			findMember.getAddressHistory().add(new Address("newCity", "street", "1000"));			
			
}}}

๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜์˜ ์ œ์•ฝ์‚ฌํ•ญ

  • ๊ฐ’ ํƒ€์ž…์€ ์—”ํ‹ฐํ‹ฐ์™€ ๋‹ค๋ฅด๊ฒŒ ์‹๋ณ„์ž ๊ฐœ๋…์ด ์—†๋‹ค.
  • ๊ฐ’์€ ๋ณ€๊ฒฝํ•˜๋ฉด ์ถ”์ ์ด ์–ด๋ ต๋‹ค.
  • ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•˜๋ฉด, ์ฃผ์ธ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๋œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๊ณ , ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜์— ์žˆ๋Š” ํ˜„์žฌ ๊ฐ’์„ ๋ชจ๋‘ ๋‹ค์‹œ ์ €์žฅํ•œ๋‹ค.
  • ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜์„ ๋งคํ•‘ํ•˜๋Š” ํ…Œ์ด๋ธ”์€ ๋ชจ๋“  ์ปฌ๋Ÿผ์„ ๋ฌถ์–ด์„œ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•จ : null ์ž…๋ ฅX, ์ค‘๋ณต ์ €์žฅ X

=> ๋”ฐ๋ผ์„œ ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๊ฐ’ ํƒ€์ž…์„ ์ˆ˜์ •ํ•˜๋ฉด ์ฟผ๋ฆฌ๊ฐ€ ์—„์ฒญ ๋งŽ์ด ์‚ญ์ œ๋˜์—ˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ์ƒ์„ฑ๋˜๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ถ”ํ›„ ๊ฐ•์˜์— ๋‚˜์˜ด.

๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜ ๋Œ€์‹  ์‚ฌ์šฉํ•  ๋Œ€์•ˆ

  • ์‹ค๋ฌด์—์„œ๋Š” ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜ ๋Œ€์‹ ์— ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค
  • ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ์œ„ํ•œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋งŒ๋“ค๊ณ , ์—ฌ๊ธฐ์—์„œ ๊ฐ’ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • ์˜์†์„ฑ ์ „์ด + ๊ณ ์•„ ๊ฐ์ฒด ์ œ๊ฑฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜ ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
  • EX)
@Entity
public class AddressEntity{
	@Id @GeneratedValue
	private Long id;
	private Address address;
	pulbic AddressEntity(String city, String street, String zipcode) {
		this.address = new Address(city, street, zipcode);
	}
	public AddressEntity(Address address) {this.address = address;)
	... // getter setter
}
@Entity
public class Member {
	...
	@Embedded
	private Address homeAddress;
	
	@ElementCollection
	@CollectionTable(name = "FAVORIT_FOOD", joinColumns = @JoinColumn(name = "MEMBER_ID"))
	private Set<String> favoriteFoods = new HashSet<>();
	
//	@ElementCollection
//	@CollectionTable(name = "ADDRESS" , joinColumns = @JoinColumn(name = "MEMBER_ID"))
//  // address ๊ฐ’ ํƒ€์ž…์„ ์—ฌ๋Ÿฌ๊ฐœ ์ €์žฅ
//	private List<Address> addressHistory = new ArrayList<>();
	@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
	@JoinColumn(name = "MEMBER_ID")
	private List<AddressEntity> addressHistory = new ArrayList<>();
		
	...
public class JpaMain {
	public static void main(String[] args) {
		...
		try{
			Member member = new Member();
			member.setUsername("member1");
			member.setAddress(new Address("HomeCity", "street", "10000"));
			
			member.getFavoritFoods().add("์น˜ํ‚จ");
			member.getFavoritFoods().add("ํ”ผ์ž");
			member.getFavoritFoods().add("์กฑ๋ฐœ");

			member.getAddressHistory().add(new AddressEntity("old1", "street", "10000"));
			member.getAddressHistory().add(new AddressEntity("old2", "street", "10000"));
}}}

๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด - ๊ธฐ๋ณธ๋ฌธ๋ฒ•

JPA๋Š” ๋‹ค์–‘ํ•œ ์ฟผ๋ฆฌ ๋ฐฉ๋ฒ•์„ ์ง€์›ํ•œ๋‹ค.

  • JPQL, JPA Criteria, QueryDSL, ๋„ค์ดํ‹ฐ๋ธŒ SQL, (JPQL์ด ์•ˆ๋  ๋•Œ)JDBC API ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ MyBatis, SpringJdbcTemplate์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

JPQL

  • ํ•„์š” ์ด์œ :

    • ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ์กฐํšŒ ๋ฐฉ๋ฒ•์€ EntityManager.find() ํ˜น์€ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰(a.getB().getC())์ด๋‹ค.
    • ํ•˜์ง€๋งŒ,,, ๋‚˜์ด๊ฐ€ 18์‚ด ์ด์ƒ์ธ ํšŒ์›์„ ๋ชจ๋‘ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜์ง€? ๋ผ๋Š” ๊ฒƒ์ด ์ถœ๋ฐœ์ ์ด๋‹ค.
    • JPQL์€ sql๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•œ ๋ฌธ๋ฒ•์ด ์ œ๊ณต์ด ๋œ๋‹ค.
    • JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ๋˜๋ฉด ์šฐ๋ฆฌ๋Š” ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด ์ค‘์‹ฌ์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•ด์•ผํ•œ๋‹ค.
    • ์ด๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋Š” ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ฒ€์ƒ‰์„ ํ•  ๋•Œ๋„ ํ…Œ์ด๋ธ”์ด ์•„๋‹Œ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.
    • ๋ชจ๋“  DB ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์€ ํ˜„์‹ค์ ์œผ๋กœ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ DB์—์„œ ๋ถˆ๋Ÿฌ์˜ค๋ ค๋ฉด ๊ฒฐ๊ตญ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์ด ํฌํ•จ๋œ SQL์ด ํ•„์š”ํ•˜๋‹ค.
  • JPQL์ด๋ž€?

    • JPA๋Š” SQL์„ ์ถ”์ƒํ™”ํ•œ JPQL์ด๋ผ๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    • ์ด๋Š” SQL ๋ฌธ๋ฒ• SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ด์ค€๋‹ค.
    • JPQL์€ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฐ๋‹ค. ์ฆ‰, ๊ฐ์ œ ์ง€ํ–ฅ SQL์ด๋‹ค.
    • SQL ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฐ๋‹ค๋Š” ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.
    • ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค Sql์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
     try{
     	List<Member> result = em.createQuery(
     		"select m From Member as m where m.username like "%kim%", Member.class).getResultList();
     		}

    ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•œ Member์€ ํ…Œ์ด๋ธ”์ด ์•„๋‹ˆ๋ผ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋™์  ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ธฐ ๋งค์šฐ ์–ด๋ ต๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ Criteria๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

  • Criteria์ด๋ž€?
    • ๋ฌธ์ž๊ฐ€ ์•„๋‹Œ ์ž๋ฐ”์ฝ”๋“œ๋กœ jpql์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
    • jpql ๋นŒ๋” ์—ญํ• ์„ ํ•œ๋‹ค
    • jpq ๊ณต์‹ ๊ธฐ๋Šฅ์ด๋‹ค.
    • ๋‹จ์ : ๋„ˆ๋ฌด ๋ณต์žกํ•˜๊ณ  ์‹ค์šฉ์„ฑ์ด ์—†๋‹ค.
    • ๋Œ€์‹  QueryDSL์„ ์‚ฌ์šฉํ•˜๊ธธ ๊ถŒ์žฅํ•œ๋‹ค.

try{
	// criteria ์‚ฌ์šฉ ์ค€๋น„
	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<Member> query = cb.createQuery(Member.class);
	
	Root<Member> m = query.from(Member.class);
	
	CriteriaQuery<Member> cq = query.select(m)
	
	String username = "hyunbins";
	if(username != null){
		cq = cq.where(cb.equal(m.get("username"), "kim"));
	}
	List<Member> resultList = em.createQuery(cq).getresultLIst();
}

์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งœ๋ฉด ์˜ค๋ฅ˜๋ฅผ ์‰ฝ๊ฒŒ ์žก๊ณ , ๋™์  ์ปค๋ฆฌ๋ฅผ ์งœ๊ธฐ๊ฐ€ ๋น„๊ต์  ๋งค์šฐ ์‰ฝ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค๊ณ  ๋Š๋‚„์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๋‹จ์ ๋„ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  sql์Šค๋Ÿฝ์ง€๊ฐ€ ์•Š๋‹ค. ์˜ํ•œ ์•„์ €์”จ๋„ ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•œ๋‹ค.

QueryDSL

  • ๋ฌธ์ž๊ฐ€ ์•„๋‹Œ ์ž๋ฐ”์ฝ”๋“œ๋กœ JPQL์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • JPQL ๋นŒ๋” ์—ญํ• ์„ ํ•œ๋‹ค
  • ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ฌธ๋ฒ• ์˜ค๋ฅ˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋™์  ์ฟผ๋ฆฌ ์ž‘์„ฑ์ด ๋งค์šฐ ํŽธ๋ฆฌํ•˜๋‹ค.
  • ๋‹จ์ˆœํ•˜๊ณ  ์‰ฝ๋‹ค.
  • ์‹ค๋ฌด ์‚ฌ์šฉํ•˜๊ธธ ๊ถŒ์žฅํ•œ๋‹ค.
@Override
public List<Order> findAllByQuerydsl(OrderSearch orderSearch){
	return queryFactory
		.select(order)
		.from(order)
		.join(order.member, member)
		.where(statusEq(orderSearch), memberNameEq(orderSearch))
		.fetch();
}

### ๋„ค์ดํ‹ฐ๋ธŒ SQL
- JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” SQL์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. 
- JPQL๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์˜์กด์ ์ธ ๊ธฐ๋Šฅ์ด๋‹ค.
- ex) ์˜ค๋ผํด CONNECT BY, ํŠน์ • db๋งŒ ์‚ฌ์šฉํ•˜๋Š” SQL ํžŒํŠธ

```java
try{
	em.createNativeQuery("select MEMBER_ID, city, street, zipcode, USERNAME from MEMBER").getResultList();
}

JDBC ์ง์ ‘ ์‚ฌ์šฉ, SpringJdbcTemplate ๋“ฑ์˜ ๋ฐฉ๋ฒ•

  • JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ JDBC ์ปค๋„ฅ์…˜์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์Šคํ”„๋ง JdbcTemplate, ๋งˆ์ด๋ฐ”ํ‹ฐ์Šค ๋“ฑ์„ ํ•จ๊ป˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ํ•˜์ง€๋งŒ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ ์ ˆํ•œ ์‹œ์ ์— ๊ฐ•์ œ๋กœ ํ”Œ๋Ÿฌ์‹œ ํ•ด์•ผํ•œ๋‹ค.
  • EX) JPA๋ฅผ ์šฐํšŒํ•ด์„œ SQL์„ ์‹คํ–‰ํ•˜๊ธฐ ์ง์ „์— ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ”Œ๋Ÿฌ์‹œํ•ด์•ผํ•œ๋‹ค.
  • ์˜ํ•œ ์•„์ €์”จ๋„ ์ฃผ๋กœ ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๋ณด๋‹ค๋Š” ์ด๊ฑธ ๋” ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

JPQL - ๊ธฐ๋ณธ ๋ฌธ๋ฒ•๊ณผ ๊ธฐ๋Šฅ

JPQL = Java Persistence Query Language

  • JPQL์€ SQL์„ ์ถ”์ƒํ™”ํ•ด์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค SQL์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • JPQL์€ ๊ฒฐ๊ตญ SQL๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

JPQL ๋ฌธ๋ฒ•

  • select m from Member as m where m.age> 18
  • ์—”ํ‹ฐํ‹ฐ์™€ ์†์„ฑ์€ ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ O (Member, age)
  • JPQL ํ‚ค์›Œ๋“œ๋Š” ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ X (SELECT, FROM, where)
  • ์—”ํ‹ฐํ‹ฐ ์ด๋ฆ„ ์‚ฌ์šฉ, ํ…Œ์ด๋ธ” ์ด๋ฆ„ ์•„๋‹˜(Member)
  • ๋ณ„์นญ์€ ํ•„์ˆ˜(m) (as๋Š” ์ƒ๋žต ๊ฐ€๋Šฅ)

TypeQuery, Query

  • TypeQuery: ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ช…ํ™œํ•  ๋•Œ ์‚ฌ์šฉ
  • Query: ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์„ ๋•Œ ์‚ฌ์šฉ
TypeQuery<Member> query = em.createQuery("SELECT m FROM Member m", Member.class);
Query query = em.createQuery("SELECT m.username, m.age from Member m");























	
	

# JPA ํ™œ์šฉ1

### MemberRepository

@PsersistenceContext: entity ๋งค๋‹ˆ์ € - spring boot๊ฐ€ ์ด ์–ด๋…ธํƒœ์ด์…˜์ด ์žˆ๋‹ค๋ฉด entity ๋งค๋‹ˆ์ €๋ฅผ ์ฃผ์ž…ํ•ด์ค€๋‹ค.



**return type ์ฃผ์˜ํ•˜๊ธฐ**

```java
@PersistenceContext // entity ๋งค๋‹ˆ์ € - spring boot๊ฐ€ ์ด ์–ด๋…ธํƒœ์ด์…˜์ด ์žˆ๋‹ค๋ฉด entity ๋งค๋‹ˆ์ €๋ฅผ ์ฃผ์ž…ํ•ด์ค€๋‹ค.
    private EntityManager em;

    public Long save(Member member){
        em.persist(member);
        return member.getId();
    }

๋กœ์ง ์„ค๋ช…: member๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ฉค๋ฒ„์˜ ์•„์ด๋””๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

์™œ Member ์ž์ฒด๋กœ ๋ฆฌํ„ดํ•˜์ง€ ์•Š๊ณ  ์•„์ด๋”” ๊ฐ’๋งŒ ๋ฆฌํ„ด ํ–ˆ์„๊นŒ?

์ปค๋ฉ˜๋“œ์™€ ์ฟผ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋ผ๋Š” ์›์น™์— ์˜ํ•ด์„œ์ด๋‹ค. ์ €์žฅ ๋กœ์ง์€ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ์ผ์œผํ‚ค๋Š” ์ปค๋ฉ˜๋“œ ์„ฑ๊ฒฉ์ด ๋†’๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๊ธ‰์  ๋ฆฌํ„ด ๊ฐ’์€ ์•ˆ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ํ•˜์ง€๋งŒ ์•„์ด๋””๋งŒ ์žˆ๋‹ค๋ฉด ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ˆ ์•„์ด๋”” ๊ฐ’๋งŒ ์ ๋Š”๋‹ค.

Entity manage๋ฅผ ํ†ตํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์€ ํŠธ๋ Œ์ ์…˜์—์„œ ์ด๋ฃจ์–ด์ ธ์•ผํ•œ๋‹ค.


๋„๋ฉ”์ธ ๋ถ„์„ ์„ค๊ณ„

์š”๊ตฌ์‚ฌํ•ญ ๋ถ„์„: ๋งค์šฐ ๊ฐ„๋‹จํ•œ ์‡ผํ•‘๋ชฐ์ด๋‹ค.

  1. ํšŒ์› ๊ฐ€์ž…, ๋ชฉ๋ก

    ID ์†์„ฑ
    1 ์ด๋ฆ„
    2 ๋„์‹œ
    3 ๊ฑฐ๋ฆฌ
    4 ์šฐํŽธ๋ฒˆํ˜ธ
  2. ์ƒํ’ˆ ๋“ฑ๋ก, ๋ชฉ๋ก ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ

ID ์†์„ฑ
1 ์ƒํ’ˆ๋ช…
2 ๊ฐ€๊ฒฉ
3 ์ˆ˜๋Ÿ‰
4 ์ €์ž
5 ISBN
  1. ์ƒํ’ˆ ์ฃผ๋ฌธ, ๋‚ด์—ญ ์กฐํšŒ ์‚ญ์ œ(์ƒํ’ˆ ์žฌ๊ณ  ๋Ÿ‰ ์กฐ์ ˆ ๊ธฐ๋Šฅ ํ•„์š”), ๊ฒ€์ƒ‰
ID ์†์„ฑ
1 ์ฃผ๋ฌธํšŒ์›
2 ์ƒํ’ˆ ์„ ํƒ
3 ์ฃผ๋ฌธ ์ˆ˜๋Ÿ‰

๊ธฐ๋Šฅ ๋ชฉ๋ก:

  • ํšŒ์› ๊ธฐ๋Šฅ
    • ํšŒ์› ๋“ฑ๋ก
    • ํšŒ์› ์กฐํšŒ
  • ์ƒํ’ˆ ๊ธฐ๋Šฅ
    • ์ƒํ’ˆ ๋“ฑ๋ก
    • ์ƒํ’ˆ ์ˆ˜์ •
    • ์ƒํ’ˆ ์กฐํšŒ
  • ์ฃผ๋ฌธ ๊ธฐ๋Šฅ
    • ์ƒํ’ˆ ์ฃผ๋ฌธ
    • ์ฃผ๋ฌธ ๋‚ด์—ญ ์กฐํšŒ
    • ์ฃผ๋ฌธ ์ทจ์†Œ
  • ๊ธฐํƒ€ ์š”๊ตฌ ์‚ฌํ•ญ
    • ์ƒํ’ˆ์€ ์ œ๊ณ  ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
    • ์ƒํ’ˆ์˜ ์ข…๋ฃŒ๋Š” ๋„์„œ, ์Œ๋ฐ˜, ์˜ํ™”๊ฐ€ ์žˆ๋‹ค.
    • ์ƒํ’ˆ์„ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์ƒํ’ˆ ์ฃผ๋ฌธ์‹œ ๋ฐฐ์†ก ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

About

๐Ÿ‘ปJPA ๊ฐœ๋… ์ •๋ฆฌ & ํ”„๋กœ์ ํŠธ๐Ÿ‘ป

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages