๊ด€๋ฆฌ ๋ฉ”๋‰ด

์‚ถ์˜ ๊ณต์œ 

[Spring] JPA, Entity, EntityManager ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ ๋ณธ๋ฌธ

Web Dev/BackEnd

[Spring] JPA, Entity, EntityManager ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ

dkrehd 2025. 5. 6. 02:15
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ” JPA์™€ Entity, EntityManager ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ

์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜์€ Java Spring์—์„œ ์ •๋ง ์ž์ฃผ ์“ฐ์ด๋Š” JPA, Entity, EntityManagerFactory, EntityManager์— ๋Œ€ํ•ด ์•„์ฃผ ์‰ฝ๊ฒŒ ์•Œ๋ ค๋“œ๋ฆด๊ฒŒ์š”. ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ๋งˆํŠธ์—์„œ ๋ฌผ๊ฑด์„ ์‚ฌ๊ณ  ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ์–ตํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๊ฑฐ๋“ ์š” ๐Ÿ˜Š


๐Ÿ“˜ 1. JPA๋ž€?

์ฝ”๋”ฉ์„ ํ•˜๋‹ค ๋ณด๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ํ”„๋กœ๊ทธ๋žจ์˜ ์ค‘์š”ํ•œ ์ •๋ณด๋“ค(์˜ˆ: ๊ฒŒ์ž„ ์ ์ˆ˜, ์นœ๊ตฌ ๋ชฉ๋ก)์„ ์ปดํ“จํ„ฐ๋ฅผ ๊ป๋‹ค ์ผœ๋„ ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ฒŒ ์ €์žฅํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ์ฃ ? ์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํŠน๋ณ„ํ•œ ์ €์žฅ์†Œ๊ฐ€ ๋ฐ”๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(Database) ๋ž๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ปดํ“จํ„ฐ ํ”„๋กœ๊ทธ๋žจ(ํŠนํžˆ ์ž๋ฐ”!)์ด๋ž‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์„œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์–ธ์–ด๊ฐ€ ์กฐ๊ธˆ ๋‹ฌ๋ผ์š”. ์ž๋ฐ”๋Š” ๊ฐ์ฒด(Object)๋ผ๋Š” ๋ ˆ๊ณ  ๋ธ”๋ก์ฒ˜๋Ÿผ ์ƒ๊ธด ์นœ๊ตฌ๋“ค์„ ์ข‹์•„ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํ‘œ(Table) ํ˜•ํƒœ๋กœ ์ •๋ฆฌํ•˜๋Š” ๊ฑธ ์ข‹์•„ํ•˜์ฃ . ๊ทธ๋ž˜์„œ ์„œ๋กœ ๋Œ€ํ™”ํ•˜๊ธฐ๊ฐ€ ์กฐ๊ธˆ ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ํ•œ๊ตญ๋ง ํ•˜๋Š” ์นœ๊ตฌ์™€ ์˜์–ด ์“ฐ๋Š” ์นœ๊ตฌ๊ฐ€ ๋Œ€ํ™”ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”!

์ด๋•Œ ์งœ์ž”โœจ ํ•˜๊ณ  ๋‚˜ํƒ€๋‚˜ ๋„์›€์„ ์ฃผ๋Š” ์นœ๊ตฌ๊ฐ€ ๋ฐ”๋กœ JPA(Java Persistence API) ๋ž๋‹ˆ๋‹ค. JPA๋Š” ์ž๋ฐ” ์นœ๊ตฌ์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์นœ๊ตฌ ์‚ฌ์ด์—์„œ ๋˜‘๋˜‘ํ•˜๊ฒŒ ๋ฒˆ์—ญ์„ ํ•ด์ฃผ๋Š” ๋ฒˆ์—ญ ๊ทœ์น™(ํ‘œ์ค€ API) ์ด์—์š”.


์‰ฝ๊ฒŒ ๋งํ•ด, ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๊ฐ์ฒด(User, Product ๋“ฑ)๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(DB)์— ์ €์žฅํ•˜๊ฑฐ๋‚˜, ๊บผ๋‚ด์˜ค๊ฑฐ๋‚˜, ์‚ญ์ œํ•˜๊ฑฐ๋‚˜, ๊ณ ์น˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” ํ‘œ์ค€ API์˜ˆ์š”.

 

๐Ÿ‘‰ ๋งˆ์น˜ ์ข…์ด์— ์ด๋ฆ„์„ ์ ์–ด๋‘๊ณ , ๋‚˜์ค‘์— ๊ทธ ์ด๋ฆ„์„ ๋‹ค์‹œ ์ฐพ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ!

 

๋˜ํ•œ, JPA๋Š” ORM(Object-Relational Mapping)์˜ ์—ญํ• ๋„ ํ•ด์š”.

  • ๊ฐ์ฒด(Object) ↔ ๊ด€๊ณ„ํ˜• ํ…Œ์ด๋ธ”(Relational Table) ๊ฐ„ ๋งคํ•‘
  • ๋Œ€ํ‘œ์ ์ธ JPA ๊ตฌํ˜„์ฒด: Hibernate, EclipseLink, OpenJPA

๐Ÿ› ๏ธ 2. ORM์ด๋ž€?

JPA์™€ ORM: ๋ฒˆ์—ญ๊ฐ€์™€ ๋ฒˆ์—ญ ํšŒ์‚ฌ ์ด์•ผ๊ธฐ ๐Ÿ—บ๏ธ

  • ORM (Object-Relational Mapping): ์ž๋ฐ”์˜ ๊ฐ์ฒด(Object) ๋ ˆ๊ณ  ๋ธ”๋ก๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ด€๊ณ„ํ˜• ํ‘œ(Relational Table) ์‚ฌ์ด์˜ ๋ชจ์–‘์„ ์„œ๋กœ ๋งž์ถฐ์ฃผ๋Š”(Mapping) ๋ฒˆ์—ญ ๊ธฐ์ˆ ์ด์—์š”. ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ๋ณด๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ‘œ๋กœ ์–ด๋–ป๊ฒŒ ์ €์žฅํ• ์ง€, ๋˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ‘œ๋ฅผ ๋ณด๊ณ  ์ž๋ฐ” ๊ฐ์ฒด๋กœ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์ง€ ์•Œ๋ ค์ฃผ๋Š” ๊ฑฐ์ฃ .
  • JPA (Java Persistence API): ์ด ORM ๋ฒˆ์—ญ ๊ธฐ์ˆ ์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์ •ํ•ด๋†“์€ ํ‘œ์ค€ ๊ทœ์น™(API) ์ด์—์š”. ์—ฌ๋Ÿฌ ํšŒ์‚ฌ์—์„œ ์ด ๊ทœ์น™์„ ๋”ฐ๋ผ์„œ ์‹ค์ œ ๋ฒˆ์—ญ ํ”„๋กœ๊ทธ๋žจ(๊ตฌํ˜„์ฒด)์„ ๋งŒ๋“œ๋Š”๋ฐ, ๊ทธ์ค‘ ๊ฐ€์žฅ ์œ ๋ช…ํ•œ ํšŒ์‚ฌ๊ฐ€ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ(Hibernate) ๋ž๋‹ˆ๋‹ค. (JPA = ๋ฒˆ์—ญ ๊ทœ์น™์„œ, ํ•˜์ด๋ฒ„๋„ค์ดํŠธ = ๊ทœ์น™์„œ๋ฅผ ์ž˜ ๋”ฐ๋ฅด๋Š” ์œ ๋ช… ๋ฒˆ์—ญ ํšŒ์‚ฌ!)
  • ์˜์†์„ฑ(Persistence): ํ”„๋กœ๊ทธ๋žจ์ด ๋๋‚˜๋„ ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ณ  ๊ณ„์† ๋‚จ์•„์žˆ๋Š” ์„ฑ์งˆ์„ ๋งํ•ด์š”. JPA๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์˜์†์ ์œผ๋กœ ์ €์žฅํ•˜๋Š” ๊ฑธ ๋„์™€์ฃผ์ฃ !

์™œ ๋ฒˆ์—ญ๊ฐ€(ORM)๊ฐ€ ํ•„์š”ํ• ๊นŒ? ๐Ÿค” (๊ฐ์ฒด vs. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค)

์ž๋ฐ”๋Š” ์„ธ์ƒ์„ ๋ ˆ๊ณ  ๋ธ”๋ก(๊ฐ์ฒด)์ฒ˜๋Ÿผ ์กฐ๋ฆฝํ•ด์„œ ์ดํ•ดํ•ด์š”. ์ž๋™์ฐจ๋Š” ๋ฐ”ํ€ด, ๋ฌธ, ์—”์ง„ ๋ธ”๋ก์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์ฃ . ํ•˜์ง€๋งŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ด๊ฑธ ๋„“์€ ํ‘œ์—๋‹ค "์ž๋™์ฐจ ID: 1, ๋ฐ”ํ€ด ์ œ์กฐ์‚ฌ: ํƒ€์ด์–ดํšŒ์‚ฌ, ๋ฌธ ์ƒ‰๊น”: ๋นจ๊ฐ•..." ์ด๋Ÿฐ ์‹์œผ๋กœ ๋‚ฉ์ž‘ํ•˜๊ฒŒ ๊ธฐ๋กํ•ด์š”. ์„œ๋กœ ์ƒ๊ฐํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฅด์ฃ ?

ORM(JPA/ํ•˜์ด๋ฒ„๋„ค์ดํŠธ)์€ ์ด ๋‹ค๋ฅธ ์ƒ๊ฐ์˜ ์ฐจ์ด๋ฅผ ํ•ด๊ฒฐํ•ด์ค˜์š”. ๊ฐœ๋ฐœ์ž๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋งŒ ๋‹ค๋ฃจ๋ฉด, ORM์ด ์•Œ์•„์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ‘œ ํ˜•์‹์œผ๋กœ ๋ฐ”๊ฟ”์„œ ์ €์žฅํ•ด์ฃผ๊ณ , ํ•„์š”ํ•  ๋• ๋‹ค์‹œ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๊ฐ€์ ธ๋‹ค์ค˜์š”. ๋•๋ถ„์— ๊ฐœ๋ฐœ์ž๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์–ธ์–ด(SQL)๋ฅผ ๊นŠ๊ฒŒ ๋ชฐ๋ผ๋„ ์ž๋ฐ” ์ฝ”๋“œ์— ๋” ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์–ด์š”!

 

๊ฐ์ฒด ๋ชจ๋ธ (Java)๊ด€๊ณ„ํ˜• ๋ชจ๋ธ (DB)
ํด๋ž˜์Šค ํ…Œ์ด๋ธ”
ํ•„๋“œ (๋ณ€์ˆ˜) ์ปฌ๋Ÿผ (column)
์ธ์Šคํ„ด์Šค (๊ฐ์ฒด) ํ–‰(row)
 

โš–๏ธ 3. MyBatis vs Hibernate (SQL Mapper vs ORM Framework)

ํ•ญ๋ชฉMyBatisHibernate(JPA)
SQL ์ž‘์„ฑ ์ง์ ‘ ์ž‘์„ฑ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋จ
์œ ์—ฐ์„ฑ ๋†’์Œ ์„ค๊ณ„๊ฐ€ ์ค‘์š”ํ•จ
๋ฐ˜๋ณต ์ž‘์—… ๋งŽ์Œ ์ ์Œ (์ž๋™ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ)

 

 

  • SQL Mapper (MyBatis ๊ฐ™์€ ์นœ๊ตฌ): ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ SQL(๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์–ธ์–ด)์„ ์จ์•ผ ํ•ด์š”. ์ข€ ๋” ๊ท€์ฐฎ์ง€๋งŒ, ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์กฐ์ข…ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์ข‹์•„์š”.

ORM (Hibernate ๊ฐ™์€ ์นœ๊ตฌ): ์›ฌ๋งŒํ•œ SQL์€ ์ž๊ธฐ๊ฐ€ ์•Œ์•„์„œ ๋งŒ๋“ค์–ด์ค˜์š”. ๊ฐœ๋ฐœ์ž๋Š” ์ž๋ฐ” ๊ฐ์ฒด์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋˜๋‹ˆ ํŽธํ•˜์ฃ ! ํ•˜์ง€๋งŒ ๊ฐ€๋” ๋ณต์žกํ•œ ์ž‘์—…์€ ORM์ด ๋งŒ๋“  SQL์ด ๋‚ด ๋ง˜์— ์•ˆ ๋“ค ์ˆ˜๋„ ์žˆ์–ด์š”.

 


๐Ÿ” 4. Spring Data JPA๋ž€?

  • Spring์—์„œ JPA๋ฅผ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ๋„์™€์ฃผ๋Š” ๋„๊ตฌ์˜ˆ์š”.
  • JpaRepository๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์‚ฌ์šฉํ•˜๋ฉด CRUD(์ƒ์„ฑ/์กฐํšŒ/์ˆ˜์ •/์‚ญ์ œ)๋ฅผ ์†์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ‘‰ ์ผ์ผ์ด ์ฝ”๋”ฉ ์•ˆ ํ•ด๋„, ํ•„์š”ํ•œ ํ•จ์ˆ˜๋งŒ ํ˜ธ์ถœํ•˜๋ฉด ๋!

๋งˆ์น˜ ๋ฆฌ๋ชจ์ปจ ํ•˜๋‚˜๋กœ TV ์ „์›, ์ฑ„๋„, ์Œ๋Ÿ‰์„ ์กฐ์ ˆํ•˜๋Š” ๋А๋‚Œ์ด์—์š” ๐ŸŽฎ


๐Ÿงฑ 5. Entity๋ž€?

Entity๋Š” DB์— ์ €์žฅ๋  ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•œ ๊ฑฐ์˜ˆ์š”.

์˜ˆ:

@Entity
public class User {
  @Id
  private String id;
  private String name;
}
 
  • @Entity: ์ด ํด๋ž˜์Šค๋Š” ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ฒฐ๋จ
  • @Id: ์ด ์†์„ฑ์ด ํ…Œ์ด๋ธ”์˜ Primary Key (๊ณ ์œ  ์‹๋ณ„์ž)

๋งˆ์น˜ ํ•™์ƒ์ฆ์˜ ํ•™๋ฒˆ์ด ๊ณ ์œ ํ•˜๋“ฏ, ํ•˜๋‚˜์˜ id๋Š” ํ•œ ์‚ฌ๋žŒ์„ ๋Œ€ํ‘œํ•ด์š”!


๐Ÿญ 6.๋ฐ์ดํ„ฐ ๋งˆ๋ฒ•์‚ฌ ๋“ฑ์žฅ! EntityManagerFactory์™€ EntityManager ๐Ÿง™‍โ™‚๏ธ

JPA๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋‘ ๋ช…์˜ ๋งˆ๋ฒ•์‚ฌ๊ฐ€ ๋“ฑ์žฅํ•ด์š”.

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

์™œ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฃผ๋ฌธํ•˜์ง€ ์•Š๊ณ , ๋งˆ๋ฒ• ์ง€ํŒก์ด(EntityManager)๋ฅผ ์“ธ๊นŒ์š”?

๋งˆ๋ฒ• ์ง€ํŒก์ด๋ฅผ ์“ฐ๋Š” ์ด์œ ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์–ด์š”!

  • ์ถ”์ƒํ™”: ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์–ธ์–ด(SQL)๋ฅผ ๋ชฐ๋ผ๋„, ์ง€ํŒก์ด์—๊ฒŒ "์ด๊ฑฐ ์ €์žฅํ•ด์ค˜!", "์ €๊ฑฐ ์ฐพ์•„์ค˜!" ๋ผ๊ณ  ์ž๋ฐ” ์–ธ์–ด๋กœ ๋งํ•˜๋ฉด ์ง€ํŒก์ด๊ฐ€ ์•Œ์•„์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์–ธ์–ด๋กœ ๋ฐ”๊ฟ”์„œ ๋ช…๋ นํ•ด์ค˜์š”. ํ›จ์”ฌ ์‰ฝ์ฃ !
  • ์บ์‹ฑ (๊ธฐ์–ต๋ ฅ): ๋งˆ๋ฒ• ์ง€ํŒก์ด๋Š” ํ•œ๋ฒˆ ์ฐพ์•„์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ž ์‹œ ๊ธฐ์–ตํ•ด๋‘๋Š” ๋˜‘๋˜‘ํ•œ ๋Šฅ๋ ฅ์ด ์žˆ์–ด์š”(์ด๊ฑธ '์บ์‹œ'๋ผ๊ณ  ํ•ด์š”). ๊ทธ๋ž˜์„œ ๋˜‘๊ฐ™์€ ๊ฑธ ๋˜ ์ฐพ์•„๋‹ฌ๋ผ๊ณ  ํ•˜๋ฉด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊นŒ์ง€ ๊ฐ€์ง€ ์•Š๊ณ  ์ž๊ธฐ๊ฐ€ ๊ธฐ์–ตํ•ด ๋‘” ๊ฑธ ๋ฐ”๋กœ ๊บผ๋‚ด์ค˜์„œ ์—„์ฒญ ๋นจ๋ผ์š”!
  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ: ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ค‘์š”ํ•œ ๋งˆ๋ฒ•์„ ํ•˜๋‚˜์˜ ๋ฌถ์Œ์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋„์™€์ค˜์š” (๋’ค์—์„œ ๋” ์ž์„ธํžˆ!).
  • ๋ณ€๊ฒฝ ๊ฐ์ง€: ์ง€ํŒก์ด๊ฐ€ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ๋ฉด, ์•Œ์•„์„œ ๊ฐ์ง€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋„ ์—…๋ฐ์ดํŠธ ํ•ด์ค˜์š”!

๋งˆ๋ฒ• ์ง€ํŒก์ด(EntityManager)์˜ ๊ธฐ๋ณธ ์ฃผ๋ฌธ:

  • persist(๊ฐ์ฒด): "์ด ๊ฐ์ฒด ์ •๋ณด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•  ์ค€๋น„๋ฅผ ํ•ด์ค˜! (๊ธฐ์–ตํ•ด์ค˜!)"
  • find(ํด๋ž˜์Šค, ID): "์ด ID๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด ์ •๋ณด๋ฅผ ์ฐพ์•„์ค˜!"
  • remove(๊ฐ์ฒด): "์ด ๊ฐ์ฒด ์ •๋ณด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์‚ญ์ œํ•  ์ค€๋น„๋ฅผ ํ•ด์ค˜! (์žŠ์–ด๋ฒ„๋ ค!)"
  • ๋ณ€๊ฒฝ(Update): ๋”ฐ๋กœ ์ฃผ๋ฌธ์ด ์—†์–ด์š”! find๋กœ ์ฐพ์•„์˜จ ๊ฐ์ฒด์˜ ๋‚ด์šฉ์„ ์ž๋ฐ” ์ฝ”๋“œ์—์„œ ๋ฐ”๊พธ๊ธฐ๋งŒ ํ•˜๋ฉด(user.setPassword("์ƒˆ ๋น„๋ฒˆ"); ์ฒ˜๋Ÿผ), ๋‚˜์ค‘์— ์ง€ํŒก์ด๊ฐ€ ์•Œ์•„์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋„ ๋ฐ˜์˜ํ•ด์ค€๋‹ต๋‹ˆ๋‹ค! (์—„์ฒญ ์‹ ๊ธฐํ•˜์ฃ ?)

โš™๏ธ 7. ํŠธ๋žœ์žญ์…˜(Transaction)

ํŠธ๋žœ์žญ์…˜์ด๋ž€ ํ•˜๋‚˜๋กœ ๋ฌถ์ธ ์ž‘์—…์ด์—์š”.
๋งŒ์•ฝ ์นœ๊ตฌ์—๊ฒŒ ๋ˆ์„ ๋ณด๋‚ด๋Š” ๋งˆ๋ฒ•์„ ์“ด๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด์š”. ๋‚ด ํ†ต์žฅ์—์„œ ๋ˆ์ด ๋น ์ ธ๋‚˜๊ฐ€๊ณ (-1000์›), ์นœ๊ตฌ ํ†ต์žฅ์— ๋ˆ์ด ๋“ค์–ด๊ฐ€์•ผ(+1000์›) ์„ฑ๊ณต์ด์ฃ ? ๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ๋‚ด ๋ˆ๋งŒ ๋น ์ ธ๋‚˜๊ฐ€๊ณ  ์นœ๊ตฌ์—๊ฒŒ ๋ˆ์ด ์•ˆ ๋“ค์–ด๊ฐ€๋Š” ๋งˆ๋ฒ• ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ธด๋‹ค๋ฉด? ํฐ์ผ ๋‚˜๊ฒ ์ฃ !

ํŠธ๋žœ์žญ์…˜(Transaction) ์€ ์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋งˆ๋ฒ•(์ž‘์—…)์„ ํ•˜๋‚˜์˜ ๋ฉ์–ด๋ฆฌ๋กœ ๋ฌถ์–ด์„œ, ์ „๋ถ€ ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜ ์ „๋ถ€ ์‹คํŒจํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์•„์ฃผ ์ค‘์š”ํ•œ ๊ทœ์น™์ด์—์š”. "๋ชจ ์•„๋‹ˆ๋ฉด ๋„!" ์ฃ . ์ค‘๊ฐ„์— ํ•˜๋‚˜๋ผ๋„ ์‹คํŒจํ•˜๋ฉด ๋ชจ๋“  ๊ฑธ ์—†๋˜ ์ผ๋กœ ๋˜๋Œ๋ ค์š”. ๊ทธ๋ž˜์•ผ ๋ฐ์ดํ„ฐ๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ์œ ์ง€๋˜๊ฒ ์ฃ ?

์„ฑ๊ณต! vs ๋˜๋Œ๋ฆฌ๊ธฐ! : ์ปค๋ฐ‹(Commit)๊ณผ ๋กค๋ฐฑ(Rollback) โœ…โŒ

ํŠธ๋žœ์žญ์…˜์ด๋ผ๋Š” ๋งˆ๋ฒ• ๋ฌถ์Œ์„ ์‹คํ–‰ํ•˜๊ณ  ๋‚˜์„œ, ๋‘ ๊ฐ€์ง€ ๊ฒฐ์ •์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

  • ์ปค๋ฐ‹ (Commit): "๋ฌถ์Œ ๋งˆ๋ฒ• ๋ชจ๋‘ ์„ฑ๊ณต! ์ด ๊ฒฐ๊ณผ๋ฅผ ์ง„์งœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์˜์›ํžˆ ์ €์žฅํ•ด์ค˜!" ๋ผ๊ณ  ํ™•์ •ํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ๊ฒŒ์ž„์—์„œ '์ €์žฅ' ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ์ปค๋ฐ‹ํ•˜๊ณ  ๋‚˜๋ฉด ๋˜๋Œ๋ฆด ์ˆ˜ ์—†์–ด์š”.
  • ๋กค๋ฐฑ (Rollback): "์–ด๋ผ? ๋งˆ๋ฒ• ๋ฌถ์Œ ์ค‘๊ฐ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋„ค! ๊ทธ๋ƒฅ ๋‹ค ์—†๋˜ ์ผ๋กœ ํ•˜๊ณ , ๋งจ ์ฒ˜์Œ ์ƒํƒœ๋กœ ๋˜๋Œ๋ ค์ค˜!" ๋ผ๊ณ  ํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ๊ฒŒ์ž„ ์ €์žฅ ์ „์œผ๋กœ '๋’ค๋กœ ๊ฐ€๊ธฐ' ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”.

๐Ÿง  8. PersistenceContext๋ž€?

 

๋งˆ๋ฒ• ์ง€ํŒก์ด(EntityManager)๋Š” ์‚ฌ์‹ค ๋น„๋ฐ€ ๋…ธํŠธ๋ฅผ ํ•˜๋‚˜ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”. ์ด ๋…ธํŠธ์˜ ์ด๋ฆ„์ด ๋ฐ”๋กœ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ(Persistence Context) ๋ž๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ em.persist(user) ๋ผ๊ณ  ์ฃผ๋ฌธํ•˜๋ฉด, ๋งˆ๋ฒ• ์ง€ํŒก์ด๋Š” user ์•„๋ฐ”ํƒ€ ์ •๋ณด๋ฅผ ๋ฐ”๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๋Š” ํฐ ๋„์„œ๊ด€์— ๊ฐ€์ ธ๊ฐ€์ง€ ์•Š์•„์š”. ๋Œ€์‹  ์ž๊ธฐ ๋น„๋ฐ€ ๋…ธํŠธ(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ)์— ๋จผ์ € ๋”ฑ! ์ ์–ด๋†“๋Š” ๊ฑฐ์ฃ . ์ด๋ ‡๊ฒŒ ๋…ธํŠธ์— ์ ํžŒ ์ƒํƒœ๋ฅผ '์˜์† ์ƒํƒœ(Persistent)' ๋ผ๊ณ  ๋ถˆ๋Ÿฌ์š”.

๋น„๋ฐ€ ๋…ธํŠธ(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ)๊ฐ€ ์™œ ์ข‹์„๊นŒ์š”?

  1. 1์ฐจ ์บ์‹œ (Cache): ๋น„๋ฐ€ ๋…ธํŠธ๋Š” ์ž„์‹œ ๊ธฐ์–ต ์žฅ์†Œ(์บ์‹œ) ์—ญํ• ์„ ํ•ด์š”. ๋งŒ์•ฝ ๋งˆ๋ฒ• ์ง€ํŒก์ด์—๊ฒŒ ์•„๊นŒ ๋…ธํŠธ์— ์ ์–ด๋‘” user ์•„๋ฐ”ํƒ€๋ฅผ ๋‹ค์‹œ ์ฐพ์•„๋‹ฌ๋ผ๊ณ (em.find(User.class, user.getId())) ํ•˜๋ฉด, ์ง€ํŒก์ด๋Š” ํฐ ๋„์„œ๊ด€(DB)๊นŒ์ง€ ๊ฐ€์ง€ ์•Š๊ณ  ๋…ธํŠธ์—์„œ ๋ฐ”๋กœ ์ฐพ์•„์„œ ์ค˜์š”. ์—„์ฒญ ๋น ๋ฅด๊ฒ ์ฃ ? (์ด๊ฑธ '1์ฐจ ์บ์‹œ'๋ผ๊ณ  ๋ถˆ๋Ÿฌ์š”.)
  2. ๋ณ€๊ฒฝ ๊ฐ์ง€ (Dirty Checking): ๋” ์‹ ๊ธฐํ•œ ๊ฑด, ๋…ธํŠธ์— ์ ํžŒ ์•„๋ฐ”ํƒ€ ์ •๋ณด(user)์˜ ๋‚ด์šฉ์„ ์ž๋ฐ” ์ฝ”๋“œ์—์„œ ์‚ด์ง ๋ฐ”๊พธ๋ฉด(user.setPassword("4321");), ๋งˆ๋ฒ• ์ง€ํŒก์ด๊ฐ€ ๊ทธ๊ฑธ ์ž๋™์œผ๋กœ ์•Œ์•„์ฐจ๋ ค์š”! ๊ทธ๋ฆฌ๊ณ  ๋‚˜์ค‘์— ์ปค๋ฐ‹ํ•  ๋•Œ ๋ฐ”๋€ ๋‚ด์šฉ๊นŒ์ง€ ์•Œ์•„์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋„์„œ๊ด€์— ๋ฐ˜์˜ํ•ด ์ค€๋‹ต๋‹ˆ๋‹ค. ๋”ฐ๋กœ "์ด๊ฑฐ ๋ฐ”๊ฟ”์ค˜!" ๋ผ๊ณ  ์ฃผ๋ฌธํ•  ํ•„์š”๊ฐ€ ์—†์–ด์š”!
  3. ์“ฐ๊ธฐ ์ง€์—ฐ (Transactional write-behind): persist ์ฃผ๋ฌธ์„ ํ•ด๋„, ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋ผ๋Š” SQL ๋ช…๋ น์€ ๋…ธํŠธ์—๋งŒ ์ ์–ด๋‘๊ณ  ๋ฐ”๋กœ ๋ณด๋‚ด์ง€ ์•Š์•„์š”. ๋…ธํŠธ์— ์—ฌ๋Ÿฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ(SQL ๋ช…๋ น)๋“ค์„ ๋ชจ์•„๋’€๋‹ค๊ฐ€, ๋‚˜์ค‘์— ์ปค๋ฐ‹ํ•  ๋•Œ ํ•œ๊บผ๋ฒˆ์— ๋ณด๋‚ด์ฃ . (๋งˆ์น˜ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋ฌผ๊ฑด์„ ๋‹ด์•„๋’€๋‹ค๊ฐ€ ํ•œ ๋ฒˆ์— ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”!)
  4. ์ง€์—ฐ ๋กœ๋”ฉ (Lazy Loading): (์กฐ๊ธˆ ์–ด๋ ค์šด ๋‚ด์šฉ) ์•„๋ฐ”ํƒ€์™€ ์—ฐ๊ฒฐ๋œ ๋‹ค๋ฅธ ์ •๋ณด(์˜ˆ: ์•„๋ฐ”ํƒ€๊ฐ€ ์“ด ๊ธ€ ๋ชฉ๋ก)๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ , ์ง„์งœ ํ•„์š”ํ•  ๋•Œ ๋”ฑ! ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๊ฒƒ๋„ ๋น„๋ฐ€ ๋…ธํŠธ ๋•๋ถ„์ด์ฃ .

๐Ÿงผ 9. flush() vs commit()

 

๋น„๋ฐ€ ๋…ธํŠธ(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ)์— ์ ํžŒ ๋ณ€๊ฒฝ ์‚ฌํ•ญ(SQL ๋ช…๋ น)๋“ค์€ ์–ธ์  ๊ฐ€ ์ง„์งœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋„์„œ๊ด€์— ๋ณด๋‚ด์•ผ๊ฒ ์ฃ ? ์ด๋•Œ flush()์™€ commit()์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์š”.

  • flush() (ํ”Œ๋Ÿฌ์‹œ - ๋ฌผ ๋‚ด๋ฆฌ๊ธฐ!):
    • ๋งˆ๋ฒ• ์ง€ํŒก์ด๊ฐ€ ๋น„๋ฐ€ ๋…ธํŠธ์— ์ง€๊ธˆ๊นŒ์ง€ ์Œ“์ธ SQL ๋ช…๋ น๋“ค์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋„์„œ๊ด€์— ์ผ๋‹จ ๋ณด๋‚ด๋Š” ์ž‘์—…์ด์—์š”.
    • ํ•˜์ง€๋งŒ ์•„์ง ๋„์„œ๊ด€ ์‚ฌ์„œ๊ฐ€ "๋ณ€๊ฒฝ ์™„๋ฃŒ!" ๋„์žฅ์„ ์ฐ์€ ๊ฑด ์•„๋‹ˆ์—์š”. ๊ทธ๋ž˜์„œ ํ˜น์‹œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ์•„์ง ๋กค๋ฐฑ(๋˜๋Œ๋ฆฌ๊ธฐ)์ด ๊ฐ€๋Šฅํ•ด์š”.
    • flush()๋ฅผ ํ•œ๋‹ค๊ณ  ํ•ด์„œ ํŠธ๋žœ์žญ์…˜์ด ๋๋‚˜๋Š” ๊ฑด ์•„๋‹ˆ์—์š”!
  • tx.commit() (์ปค๋ฐ‹ - ํ™•์ •!):
    • "๋ชจ๋“  ์ž‘์—… ์„ฑ๊ณต! ์ด์ œ ์ง„์งœ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์˜์›ํžˆ ์ €์žฅํ•ด์ค˜!" ๋ผ๊ณ  ์ตœ์ข… ํ™•์ •ํ•˜๋Š” ๋ช…๋ น์ด์—์š”.
    • ์ปค๋ฐ‹์„ ํ•˜๋ฉด, ๋‚ด๋ถ€์ ์œผ๋กœ flush()๊ฐ€ ์ž๋™์œผ๋กœ ๋จผ์ € ํ˜ธ์ถœ๋˜์–ด์„œ ์•„์ง ๋ณด๋‚ด์ง€ ์•Š์€ SQL ๋ช…๋ น๋“ค์„ ๋ชจ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณด๋‚ด์š”.
    • ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— "๋ณ€๊ฒฝ ์™„๋ฃŒ!" ๋„์žฅ์„ ๊ฝ! ์ฐ์–ด์š”.
    • ์ปค๋ฐ‹์ด ์™„๋ฃŒ๋˜๋ฉด ํŠธ๋žœ์žญ์…˜์ด ๋๋‚˜๊ณ , ๋” ์ด์ƒ ๋กค๋ฐฑ(๋˜๋Œ๋ฆฌ๊ธฐ)์„ ํ•  ์ˆ˜ ์—†์–ด์š”.

flush()์™€ commit() ๋น„๊ต:

๊ตฌ๋ถ„flush()tx.commit()
์ฃผ์š” ์—ญํ•  ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ DB์— ๋™๊ธฐํ™” ํŠธ๋žœ์žญ์…˜ ์ž‘์—…์„ DB์— ์˜๊ตฌ ๋ฐ˜์˜ (์ž‘์—… ์ตœ์ข… ํ™•์ •)
SQL ์ „์†ก O (์“ฐ๊ธฐ ์ง€์—ฐ SQL ์ €์žฅ์†Œ์˜ ์ฟผ๋ฆฌ๋ฅผ DB๋กœ ์ „์†ก) O (flush() ์ž๋™ ํ˜ธ์ถœ ํฌํ•จ)
DB ๋ฐ˜์˜ X (DB์— SQL์€ ๊ฐ”์ง€๋งŒ, ์•„์ง ํ™•์ • ์•„๋‹˜) O (DB์— ์˜๊ตฌ์ ์œผ๋กœ ๋ณ€๊ฒฝ ๋‚ด์šฉ ์ €์žฅ ์™„๋ฃŒ)
ํŠธ๋žœ์žญ์…˜ ์ข…๋ฃŒ X O
๋กค๋ฐฑ ๊ฐ€๋Šฅ? O (์ปค๋ฐ‹ ์ „์ด๋ฏ€๋กœ ๊ฐ€๋Šฅ) X (์ปค๋ฐ‹ ํ›„์—๋Š” ๋ถˆ๊ฐ€)

๐Ÿ’ป ์‹ค์ „! ์ฝ”๋“œ ์˜ˆ์ œ ์‚ดํŽด๋ณด๊ธฐ 

์ด์ œ ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ๋งˆ๋ฒ• ์ง€ํŒก์ด๊ฐ€ ์–ด๋–ป๊ฒŒ ์ผํ•˜๋Š”์ง€ ๋”ฐ๋ผ๊ฐ€ ๋ณผ๊นŒ์š”?

// application.java

// ... (Spring Boot ์„ค์ • ๋ถ€๋ถ„) ...

public class Sbtch4Application implements CommandLineRunner {

    @Autowired // ์Šคํ”„๋ง์•„, ๋งˆ๋ฒ• ์ง€ํŒก์ด ๊ณต์žฅ(EntityManagerFactory) ํ•˜๋‚˜ ์ค€๋น„ํ•ด์ค˜!
    EntityManagerFactory emf;

    @Override
    public void run(String... args) throws Exception {
        // 1. ๋งˆ๋ฒ• ์ง€ํŒก์ด(EntityManager) ๋งŒ๋“ค๊ธฐ
        EntityManager em = emf.createEntityManager();
        System.out.println("๋งˆ๋ฒ• ์ง€ํŒก์ด ์ค€๋น„ ์™„๋ฃŒ! em = " + em);

        // 2. ํŠธ๋žœ์žญ์…˜ ๋งˆ๋ฒ• ์ค€๋น„! (๋งˆ๋ฒ• ๋ฌถ์Œ ์ฃผ๋ฌธ์„œ)
        EntityTransaction tx =  em.getTransaction();

        // 3. ์ƒˆ๋กœ์šด User ์•„๋ฐ”ํƒ€ ๋งŒ๋“ค๊ธฐ
        User user = new User();
        user.setId("aaa"); // ๊ณ ์œ  ID ์„ค์ •
        user.setPassword("1234");
        user.setName("Lee");
        // ... (๋‹ค๋ฅธ ์ •๋ณด ์„ค์ •) ...

        // 4. ํŠธ๋žœ์žญ์…˜ ๋งˆ๋ฒ• ์‹œ์ž‘! (๋ฌถ์Œ ์ฃผ๋ฌธ ์‹œ์ž‘!)
        tx.begin();

        // 5. ์•„๋ฐ”ํƒ€ ์ •๋ณด ์ €์žฅ ์ค€๋น„! (๋น„๋ฐ€ ๋…ธํŠธ์— ์ ๊ธฐ)
        System.out.println("user ์•„๋ฐ”ํƒ€ ์ •๋ณด๋ฅผ ๋น„๋ฐ€ ๋…ธํŠธ์— ์ ์„๊ฒŒ์š”! (persist)");
        em.persist(user);
        // ๋˜‘๊ฐ™์€ user๋ฅผ ๋˜ persist ํ•ด๋„, ๋น„๋ฐ€ ๋…ธํŠธ์— ์ด๋ฏธ ์žˆ์œผ๋ฉด SQL์€ ํ•œ ๋ฒˆ๋งŒ ์ค€๋น„ํ•ด์š”!
        // em.persist(user); // ์ด๊ฑด ๋ฌด์‹œ๋จ

        // 6. ์•„๋ฐ”ํƒ€ ์ •๋ณด ๋ณ€๊ฒฝ! (์ž๋ฐ” ๊ฐ์ฒด ๋‚ด์šฉ ๋ฐ”๊พธ๊ธฐ)
        System.out.println("user ์•„๋ฐ”ํƒ€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ž‘ ์ด๋ฉ”์ผ์„ ๋ฐ”๊ฟ”์•ผ์ง€!");
        user.setPassword("4321"); // ๋น„๋ฐ€ ๋…ธํŠธ๊ฐ€ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•  ๊ฑฐ์˜ˆ์š”!
        user.setEmail("bbb@bbb.com");

        // 7. ํŠธ๋žœ์žญ์…˜ ๋งˆ๋ฒ• ์™„๋ฃŒ! (์ปค๋ฐ‹! DB์— ์ตœ์ข… ์ €์žฅ!)
        System.out.println("๋น„๋ฐ€ ๋…ธํŠธ ๋‚ด์šฉ์„ DB์— ์ตœ์ข… ์ €์žฅํ• ๊ฒŒ์š”! (commit)");
        tx.commit(); // ์ด๋•Œ ๋ณ€๊ฒฝ ๊ฐ์ง€๋œ update SQL์ด๋ž‘ persist ํ–ˆ๋˜ insert SQL์ด DB๋กœ ์Š!

        System.out.println("\n=== ์ €์žฅ ๋ฐ ๋ณ€๊ฒฝ ์™„๋ฃŒ! ์ด์ œ ์ฐพ์•„๋ณผ๊นŒ์š”? ===");

        // 8. ์•„๋ฐ”ํƒ€ ์ฐพ์•„๋ณด๊ธฐ (ID: aaa)
        System.out.println("ID๊ฐ€ 'aaa'์ธ ์•„๋ฐ”ํƒ€ ์ฐพ์•„์ค˜! (find)");
        User user2 = em.find(User.class, "aaa"); // ๋น„๋ฐ€ ๋…ธํŠธ(1์ฐจ ์บ์‹œ)์— ์žˆ๋Š”์ง€ ๋จผ์ € ํ™•์ธ!
        System.out.println("์ฐพ์•„์˜จ ์•„๋ฐ”ํƒ€ ์ •๋ณด: " + user2);
        System.out.println("์ฒ˜์Œ ๋งŒ๋“  user๋ž‘ ์ง€๊ธˆ ์ฐพ์€ user2๋Š” ๊ฐ™์€ ๊ฑธ๊นŒ? " + (user == user2)); // true! ์บ์‹œ์—์„œ ๊ฐ€์ ธ์™”์œผ๋‹ˆ ๊ฐ™์€ ๊ฐ์ฒด!

        // 9. ๋‹ค๋ฅธ ์•„๋ฐ”ํƒ€ ์ฐพ์•„๋ณด๊ธฐ (ID: bbb)
        System.out.println("ID๊ฐ€ 'bbb'์ธ ์•„๋ฐ”ํƒ€ ์ฐพ์•„์ค˜! (find)");
        User user3 = em.find(User.class, "bbb"); // ๋น„๋ฐ€ ๋…ธํŠธ์— ์—†๋„ค? ๊ทธ๋Ÿผ DB ๋„์„œ๊ด€์— ๋ฌผ์–ด๋ด์•ผ์ง€!
        System.out.println("์ฐพ์•„์˜จ ์•„๋ฐ”ํƒ€ ์ •๋ณด: " + user3); // null! DB์—๋„ ์—†์—ˆ๋‚˜ ๋ด์š”.

        System.out.println("\n=== ์ด์ œ ์•„๋ฐ”ํƒ€๋ฅผ ์‚ญ์ œํ•ด๋ณผ๊นŒ์š”? ===");

        // 10. ์•„๋ฐ”ํƒ€ ์‚ญ์ œํ•˜๊ธฐ
        tx.begin(); // ์‚ญ์ œ๋„ ์ค‘์š”ํ•œ ์ž‘์—…์ด๋‹ˆ ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘!
        System.out.println("ID 'aaa' ์•„๋ฐ”ํƒ€ ์‚ญ์ œ ์ค€๋น„! (remove)");
        em.remove(user); // ๋น„๋ฐ€ ๋…ธํŠธ์—์„œ ์‚ญ์ œ ํ‘œ์‹œ!
        System.out.println("์‚ญ์ œ ๋‚ด์šฉ์„ DB์— ์ตœ์ข… ๋ฐ˜์˜! (commit)");
        tx.commit(); // ์ด๋•Œ delete SQL์ด DB๋กœ ์Š!
    }
}

 

๐Ÿ“„ User Entity ํด๋ž˜์Šค

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

import java.util.Date;

@Entity
public class User {
    @Id
    private String id;
    private String password;
    private String name;
    private String email;
    private Date inDate;
    private Date upDate;

    // Getter/Setter ์ƒ๋žต ๊ฐ€๋Šฅ
    // toString()๋„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ ๋กœ๊ทธ๋กœ ๋ณด๊ธฐ ์‰ฝ๊ฒŒ ํ•จ
}

 


๐Ÿ“ Entity ๊ด€๋ จ ์• ๋„ˆํ…Œ์ด์…˜ ์ •๋ฆฌ

์• ๋„ˆํ…Œ์ด์…˜์„ค๋ช…
@Entity DB ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋˜๋Š” ํด๋ž˜์Šค
@Id ๊ธฐ๋ณธ ํ‚ค(PK) ์ง€์ •
@Table ํ…Œ์ด๋ธ” ์ด๋ฆ„ ์ง€์ •
@Column ์ปฌ๋Ÿผ ์†์„ฑ ์ง€์ •
@Enumerated Enum ํƒ€์ž… ๋งคํ•‘
@Temporal ๋‚ ์งœ/์‹œ๊ฐ„ ํƒ€์ž… ๋งคํ•‘
@Transient DB์— ์ €์žฅํ•˜์ง€ ์•Š์„ ํ•„๋“œ
@Generated ๊ฐ’ ์ž๋™ ์ƒ์„ฑ (ex. auto increment)
 

โœ… ๋งˆ๋ฌด๋ฆฌ ์ •๋ฆฌ

๊ฐœ๋…์‰ฝ๊ฒŒ ์„ค๋ช…
JPA ๊ฐ์ฒด๋ฅผ DB์— ์ €์žฅํ•˜๋Š” ํ‘œ์ค€ ๋ฐฉ๋ฒ•
ORM ๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์ž๋™ ํ†ต์—ญ์‚ฌ
Entity DB ํ…Œ์ด๋ธ”์˜ ํ•œ ์ค„ (๋ฐ์ดํ„ฐ ๋ชจ๋ธ)
EntityManager Entity๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ง์› ๊ฐ™์€ ์กด์žฌ
PersistenceContext Entity๋“ค์ด ์ž ์‹œ ๋ชจ์—ฌ์žˆ๋Š” ๊ธฐ์–ต ์ฐฝ๊ณ 
flush vs commit flush๋Š” ์ž„์‹œ ์ €์žฅ, commit์€ ์ง„์งœ ์ €์žฅ

 

๋ฐ˜์‘ํ˜•