ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

JPA

[JPA] ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ

๊ฐœ๋ฐœ๊ฐœ๊ตด๐Ÿธ 2025. 7. 13. 20:33
728x90
๋ฐ˜์‘ํ˜•

JPA(Java Persistence API)๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ์žˆ์–ด ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฐœ๋…์€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ(Persistence Context)์ž…๋‹ˆ๋‹ค. ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ์„ ์ตœ์ ํ™”ํ•˜๋Š” ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

์ด ๊ธ€์€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด JPA์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


1. ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ํŒฉํ† ๋ฆฌ์™€ ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €

JPA ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ํŒฉํ† ๋ฆฌ์™€ ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

// ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ์ƒ์„ฑ (์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ)
EntityManager em = emf.createEntityManager();

// ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
EntityTransaction transaction = em.getTransaction();
transaction.begin();

// ...์—”ํ‹ฐํ‹ฐ ์กฐ์ž‘...

// ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹
transaction.commit();
  • EntityManagerFactory๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ ์— ๋‹จ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ •๋ณด, JPA ์„ค์ • ๋“ฑ์„ ๋ฐ”ํƒ•์œผ๋กœ EntityManagerFactory์— ์˜ํ•ด EntityManager๊ฐ€ ์ƒ์„ฑ
  • EntityManager๋Š” ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅ/์กฐํšŒ/์ˆ˜์ •/์‚ญ์ œ ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ ‘๊ทผํ•˜๋Š” ํ†ต๋กœ ์—ญํ• 
    (
    ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผ)

2. ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ ์—”ํ‹ฐํ‹ฐ์˜ ์ƒ๋ช… ์ฃผ๊ธฐ

์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅํ•˜๋Š” ํ™˜๊ฒฝ์ด๋ผ๋Š” ๋…ผ๋ฆฌ์ ์ธ ๊ฐœ๋…์œผ๋กœ, EntityManager๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•จ๊ป˜ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ 4๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

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

2.1. ๋น„์˜์† (New/Transient)

// ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
Member member = new Member();
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ ์ „ํ˜€ ๊ด€๊ณ„๊ฐ€ ์—†๋Š” ์ƒˆ๋กœ์šด ์ƒํƒœ
  • ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ–ˆ์ง€๋งŒ ์•„์ง EntityManager์— ์ €์žฅ๋˜์ง€ ์•Š์Œ

2.2. ์˜์† (Managed)

// ๊ฐ์ฒด๋ฅผ ์˜์†ํ™”
em.persist(member);
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๊ด€๋ฆฌ๋˜๋Š” ์ƒํƒœ
  • persist()๋ฅผ ํ†ตํ•ด ์˜์† ์ƒํƒœ๋กœ ์ „ํ™˜๋˜๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒ๋˜์–ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๋กœ๋“œ
  • ์˜์† ์ƒํƒœ์˜ ์—”ํ‹ฐํ‹ฐ๋Š” 1์ฐจ ์บ์‹œ์— ์ €์žฅ๋˜๋ฉฐ, Dirty Checking(๋ณ€๊ฒฝ ๊ฐ์ง€)์˜ ๋Œ€์ƒ

** Spring Data JPA์˜ save() ๋ฉ”์„œ๋“œ๋Š” ์ƒˆ๋กœ์šด ์—”ํ‹ฐํ‹ฐ๋ผ๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ em.persist()๋ฅผ ํ˜ธ์ถœ

2.3. ์ค€์˜์† (Detached)

// ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ๋ถ„๋ฆฌ
em.detach(member);
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋˜์—ˆ๋‹ค๊ฐ€ ๋ถ„๋ฆฌ๋œ ์ƒํƒœ
  • detach()๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ํŠธ๋žœ์žญ์…˜์ด ์ข…๋ฃŒ๋˜๋ฉด ๋ฐœ์ƒ

2.4. ์‚ญ์ œ (Removed)

// ์‚ญ์ œ ์ƒํƒœ๋กœ ์ „ํ™˜
em.remove(member);
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ์‚ญ์ œ๋œ ์ƒํƒœ
  • remove()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ญ์ œ ์ƒํƒœ๋กœ ์ „ํ™˜

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

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

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ์บ์‹œ ๊ณต๊ฐ„

// 1์ฐจ ์บ์‹œ์— ์ €์žฅ๋จ
em.persist(member);

// 1์ฐจ ์บ์‹œ์—์„œ ์กฐํšŒ
Member findMember = em.find(Member.class, "member1");
  • persist()๋ฅผ ํ†ตํ•ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋œ ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ์กฐํšŒํ•˜๋ฉด DB๊ฐ€ ์•„๋‹Œ ์ปจํ…์ŠคํŠธ์—์„œ ์กฐํšŒ
  • ๋งŒ์•ฝ, 1์ฐจ ์บ์‹œ์— ์—†๋‹ค๋ฉด DB์—์„œ ์กฐํšŒ ํ›„ 1์ฐจ ์บ์‹œ์— ์ €์žฅ (์ด๋•Œ, ๋ฐ”๋กœ ์˜์† ์ƒํƒœ๊ฐ€ ๋จ)
  • ๋™์ผํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์—”ํ‹ฐํ‹ฐ์˜ ๋™์ผ์„ฑ์„ ๋ณด์žฅํ•˜๋ฉฐ, ๋ฐ˜๋ณต์ ์ธ ์ฝ๊ธฐ ์ž‘์—…์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ

 

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

// ์˜์† ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ
Member memberA = em.find(Member.class, "memberA");

// ์˜์† ์—”ํ‹ฐํ‹ฐ ๋ฐ์ดํ„ฐ ์ˆ˜์ •
memberA.setUsername("hi");
memberA.setAge(10);

// ์ž๋™์œผ๋กœ UPDATE ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • 1์ฐจ ์บ์‹œ ์•ˆ์˜ ์˜์† ์ƒํƒœ ์—”ํ‹ฐํ‹ฐ์™€ ์Šคํƒญ์ƒท์„ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ, JPA๊ฐ€ ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์„ ๊ฐ์ง€ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜
  • JPA๋Š” flush()๋ฅผ ํ†ตํ•ด transaction.commit() ํ˜ธ์ถœ ์‹œ์ ์— ๋ณ€๊ฒฝ ๊ฐ์ง€, ์“ฐ๊ธฐ ์ง€์—ฐ SQL ์ €์žฅ์†Œ์— ๋“ฑ๋ก, ์ €์žฅ์†Œ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ „์†กํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋Š” ์“ฐ๊ธฐ ์ง€์—ฐ (Transcation Wirte-Behind)์„ ํ†ตํ•ด ๋ชจ๋“  ์ฟผ๋ฆฌ๋“ค์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ํ•œ ๋ฒˆ์— ์ „์†กํ•˜๋Š” ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ๋กœ ์„ฑ๋Šฅ ํ–ฅ์ƒ๊ณผ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ์„ ์œ ์ง€

 

3.2.1. @Transactional(readOnly = true)์™€ Dirty Checking

@Transactional(readOnly = true)๋Š” ๋‹จ์ˆœํžˆ ์ฝ๊ธฐ ์ „์šฉ ์„ค์ •์ด๋‚˜, Master/Slave ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™˜๊ฒฝ์—์„œ ์ฝ๊ธฐ ์ „์šฉ DB๋กœ์˜ ์ฝ๊ธฐ ์ž‘์—… ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ ์™ธ์—๋„, JPA์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋™์ž‘์— ๊ด€์—ฌํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. 

@Transactional(readOnly = true)
public void updateMember(Member member) {
    member.setName("Changed Name");
    // ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ ์‹œ์ ์—๋„ UPDATE ์ฟผ๋ฆฌ ๋ฐœ์ƒ X
}
  • ํŠธ๋žœ์žญ์…˜์— readOnly๋ฅผ true๋กœ ์ ์šฉํ•˜๋ฉด, JPA๋Š” ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์ฝ๊ธฐ ์ „์šฉ์ž„์„ ์ธ์ง€ํ•˜๊ณ  Dirty Checking๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Œ
  • ์Šค๋ƒ…์ƒท ์ €์žฅ ์ƒ๋žต๊ณผ ๋ณ€๊ฒฝ ๊ฐ์ง€ ๋กœ์ง ๊ฑด๋„ˆ๋›ฐ๊ธฐ๋ฅผ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ ์Šค๋ƒ…์ƒท ๋น„๊ต ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ

[์ฐธ๊ณ ]
https://www.inflearn.com/course/ORM-JPA-Basic

 

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ ๊ฐ•์˜ | ๊น€์˜ํ•œ - ์ธํ”„๋Ÿฐ

๊น€์˜ํ•œ | JPA๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ฑฐ๋‚˜, ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์ด๋ก ์ด ๋ถ€์กฑํ•˜์‹  ๋ถ„๋“ค์ด JPA์˜ ๊ธฐ๋ณธ ์ด๋ก ์„ ํƒ„ํƒ„ํ•˜๊ฒŒ ํ•™์Šตํ•ด์„œ ์ดˆ๋ณด์ž๋„ ์‹ค๋ฌด์—์„œ ์ž์‹ ์žˆ๊ฒŒ JPA๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., ์‹ค๋ฌด์—์„œ๋„

www.inflearn.com

 

728x90
๋ฐ˜์‘ํ˜•