๐ŸŒ Backend/โœˆ๏ธŽ JPA

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

DevPoong 2022. 10. 6. 13:05

1. EntityManagerFactory์™€ EntityManager๋ฅผ ๋จผ์ € ์•Œ์•„๋ณด์ž

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ(๊น€์˜ํ•œ) ์ž๋ฃŒ

EntityManager๋ž€ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์— ๋Œ€ํ•˜์—ฌ ์ปค๋„ฅ์…˜ ํ’€์—์„œ ์ปค๋„ฅ์…˜์„ ์–ป๊ณ  DB์— ์ ‘๊ทผํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.                              EntityManagerFactory๋ž€ ๋ง ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ๋งˆ๋‹ค EntityManger๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ณต์žฅ์ด๋‹ค.

 

2. ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ญ˜๊นŒ ๊ทธ๋ž˜์„œ

๊ฐ„๋‹จํ•˜๊ฒŒ ์—”ํ‹ฐํ‹ฐ์˜ Life Cycle์„ ๊ด€๋ฆฌํ•˜๋Š” ์ €์žฅ์†Œ์ด๋‹ค.

EntityManager๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ PersistenceContext๊ฐ€ ๊ฐ™์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

 

3. Entity Life Cycle

  • ๋น„์˜์†(new/transient): ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ ๊ด€๊ณ„์—†๋Š” ์ƒˆ๋กœ์šด ์ƒํƒœ
  • ์˜์†(managed): ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๋Š” ์ƒํƒœ
  • ์ค€์˜์†(detached): ์›๋ž˜ ์˜์†์„ฑ ์ƒํƒœ์˜€๋‹ค๊ฐ€ ํ˜„์žฌ๋Š” ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋Š” ์ƒํƒœ
  • ์‚ญ์ œ(removed): ์‚ญ์ œ๋œ ์ƒํƒœ

๋น„์˜์† ์ƒํƒœ๋Š” ๊ทธ์ € new Book()์ฒ˜๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ๋งŒ ํ•ด๋†“์€ ์ƒํƒœ์ด๊ณ 

์˜์† ์ƒํƒœ๋Š” ์ƒ์„ฑ๋œ Book ์ธ์Šคํ„ด์Šค๋ฅผ EntityManager๋ฅผ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘๋˜๊ณ  persist๊ฐ€ ๋˜์–ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๋Š” ์ƒํƒœ์ด๋‹ค.

 

4. ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์€์  5๊ฐ€์ง€๋งŒ ์•Œ์•„๋ณด์ž

์—ฌ๊ธฐ์„œ๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ๋งŒ ์ ๊ณ  ์ž์„ธํ•œ๊ฑด ๋‚˜์ค‘์— ๋‹ค์‹œ ํฌ์ŠคํŒ…ํ•  ์˜ˆ์ •...

1. 1์ฐจ ์บ์‹œ                                                                                                                                          

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์— ์บ์‹œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, Map ์ž๋ฃŒํ˜•์œผ๋กœ ์ €์žฅํ•˜๋Š”๋ฐ key๋Š” Entity์—์„œ @Id๋กœ ๋งคํ•‘ํ•œ ์‹๋ณ„์ž๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ  value๋Š” Entity์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ €์žฅ๋œ๋‹ค. 

em.persist(new Book(1L, "์ฑ…1");

em.find(Book.class, 1L);

์œ„์™€ ๊ฐ™์ด persist๋ฅผ ํ†ตํ•ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” Book์— ๋Œ€ํ•ด์„œ ์กฐํšŒ๋ฅผ ํ•˜๋ฉด EntityManager๋Š” ๋จผ์ € ์˜์†์„ฑ ์ปจํ…์Šค์˜ 1์ฐจ ์บ์‹œ์— ์กด์žฌํ•˜๋Š”์ง€ ์ฐพ์•„๋ณด๊ณ  ์žˆ์œผ๋ฉด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์—†์œผ๋ฉด ๋””๋น„์—์„œ ์ฐพ์•„์™€์„œ 1์ฐจ ์บ์‹œ์— ์ €์žฅํ•˜๊ณ   ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ์บ์‹œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์ค€๋‹ค.

ํ•˜์ง€๋งŒ ์ด๊ฒŒ ์‚ฌ์‹ค์ƒ ๋งŽ์€ ์ƒํ™ฉ์— ๋„์›€์ด ์•ˆ๋ ์ˆ˜๋„ ์žˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋Š” EntityManager๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ๊ฐ™์ด ์ƒ์„ฑ๋˜๋ฉฐ ํŠธ๋žœ์žญ์…˜์ด ์ข…๋ฃŒ๋˜๋ฉด ๊ฐ™์ด ์‚ญ์ œ๊ฐ€ ๋˜๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ๋งŒ ์ด์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ „์ฒด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์บ์‹œ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด 2์ฐจ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

2. ๋™์ผ์„ฑ ๋ณด์žฅ   

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ๋˜‘๊ฐ™์€ ๊ฒƒ์„ findํ–ˆ์„ ๋•Œ ๋‘ ์ธ์Šคํ„ด์Šค๋ฅผ == ๋น„๊ตํ•˜๋ฉด true์ด๋‹ค.

ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋Š”๊ฒŒ ๋™๋“ฑ์„ฑ์€ ์‹ค์ œ ์ธ์Šคํ„ด์Šค๋Š” ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ’์ด ๊ฐ™๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋™๋“ฑ์„ฑ ๋น„๊ต๋ฅผ ์œ„ํ•ด์„œ๋Š” equals() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

1์ฐจ ์บ์‹œ๋ฅผ ํ†ตํ•ด REPEATABLE READ์˜ ํŠธ๋žœ์žญ์…˜ isolation level์„ DB๊ฐ€ ์•„๋‹Œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฐจ์›์—์„œ ์ œ๊ณตํ•œ๋‹ค.

 

3. ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋Š” ์“ฐ๊ธฐ ์ง€์—ฐ

persist ํ–ˆ์„ ๋•Œ ๋ฐ”๋กœ insert ์ฟผ๋ฆฌ๊ฐ€ ๋‚ ๋ผ๊ฐ€๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ transactional write-behind(์“ฐ๊ธฐ ์ง€์—ฐ) sql ์ €์žฅ์†Œ์— insert sql๋ฌธ์ด ์ €์žฅ๋œ๋‹ค. transaction.commit()์ด ์‹คํ–‰๋ผ์•ผ write behind sql ์ €์žฅ์†Œ์—์„œ flush(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ DB์— ๋ฐ˜์˜ํ•˜๋Š” ๊ฒƒ)๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ   ์‹ค์ œ DB์— insert ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค ๊ทธ๋ฆฌ๊ณ  commit(์‹ค์ œ ํŠธ๋žœ์žญ์…˜์„ ์ข…๋ฃŒํ•˜๊ณ  ๋ชจ๋“  ์ž‘์—…์„ ์ •์ƒ ์ฒ˜๋ฆฌ ํ™•์ •ํ•˜๋Š” ๊ฒƒ)์ด ๋˜์–ด ์ข…๋ฃŒ๋œ๋‹ค.

์“ฐ๊ธฐ ์ง€์—ฐ SQL ์ €์žฅ์†Œ์— ์ €์žฅํ•˜๋ฉด์„œ 1์ฐจ ์บ์‹œ์—๋„ ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•œ๋‹ค.

๋ฒ„ํผ๋ง์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ insert๋ฅผ commit ์ „์— ๋ชจ์•„๋†จ๋‹ค๊ฐ€ commit ํ•˜๋ฉด batch size ์„ค์ •ํ•œ๋งŒํผ ํ•œ๋ฐฉ์— insert์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

<property name="hibernate.jdbc.batch_size" value="10"/>

 

4. ๋ณ€๊ฒฝ ๊ฐ์ง€(Dirty Checking)                                                                                                                                                                           

Book book1 = em.find(Book.class, 1L);
book1.setName("์ฑ…์ด๋ฆ„์ˆ˜์ •");

์ด๋•Œ, ํŠธ๋žœ์žญ์…˜๋‚ด์—์„œ ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค๋ฉด find๋ฅผ ์‹คํ–‰ํ•˜๋ฉด book1 ์ธ์Šคํ„ด์Šค๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์˜ํ•ด ๊ด€๋ฆฌ๊ฐ€ ๋˜๊ณ  book1์„ ์ˆ˜์ •ํ•˜๋ฉด commit ์‹œ์ ์— ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ฐ˜์˜๋œ๋‹ค. ๋”ฐ๋กœ persist๋ฅผ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

์กฐ๊ธˆ ์ž์„ธํ•˜๊ฒŒ ๋งํ•˜์ž๋ฉด

1์ฐจ์บ์‹œ์—๋Š” @Id๋กœ ์„ค์ •ํ•ด๋‘” ์‹๋ณ„์ž, ์—”ํ‹ฐํ‹ฐ ์ธ์Šคํ„ด์Šค์™ธ์—๋„ Snapshot์ด๋ผ๋Š” ํ•„๋“œ๊ฐ€ ๋” ์žˆ๋‹ค. ์Šค๋ƒ…์ƒท์€ ์ตœ์ดˆ์— ์—”ํ‹ฐํ‹ฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ์˜์†์„ฑ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•ด๋‘”๊ฒƒ์ด๋‹ค.

(1)transaction.flush()๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ (2)ํ˜„์žฌ ์—”ํ‹ฐํ‹ฐ ์ธ์Šคํ„ด์Šค์™€ ์Šค๋ƒ…์ƒท๊ฐ„์˜ ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค๋ฉด (3)Update Sql๋ฌธ์„ ์ƒ์„ฑํ•ด์„œ ์“ฐ๊ธฐ ์ง€์—ฐ Sql ์ €์žฅ์†Œ์— ์ƒ์„ฑํ•˜๊ณ  ์‹ค์ œ DB๋กœ (4)flush๋˜๊ณ  (commit ํ›„ ์ข…๋ฃŒ๋œ๋‹ค. 

5. ์ง€์—ฐ ๋กœ๋”ฉ

์ง€์—ฐ ๋กœ๋”ฉ์ด๋ž€ ๋งŒ์•ฝ์— ์กฐ์ธ ์ปฌ๋Ÿผ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์—์„œ ์กฐ์ธ๋œ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋Š” ์ฒ˜์Œ ๋””๋น„์— ์กฐํšŒ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ธ์„ ๋•Œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ  ๋‚˜์ค‘์— ์กฐ์ธ๋œ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ get์š”์ฒญ์„ ์ง„ํ–‰ํ•˜๋ฉด ๊ทธ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์ด๋‹ค. lazy loading ์˜๋ฏธ๋Œ€๋กœ ๊ฒŒ์œผ๋ฅธ ๋กœ๋”ฉ์œผ๋กœ ๊ธฐ์–ตํ•˜๋ฉด ๋œ๋‹ค!