์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- ๋ถ๋์ฐ
- ๋ฐ์ด๋ธ์ค
- ์ํธํํ
- ๊ฒฝ์ ์งํ
- ๊ตญ๋ด์ฌํ
- ํธ๋ ์ด๋ฉ
- ํ์ด์ฌ
- ๊ฒฝ์
- ์งํ
- ๋งค๋งค์ ๋ต
- ์ผ์
- ๊ธ๋ฆฌ
- ์ฃผ์
- ์ฐจํธ๋ถ์
- ์ด๋๋ฆฌ์
- Python
- ํฌ์
- ์ธ๊ณ๊ฒฝ์
- ๋ฐ์ดํฐ๋ถ์
- ๋ง์ง
- C++
- ์ฌํ
- ํ๋ก๊ทธ๋๋ฐ
- ํด์ธ์ฌํ
- ๋ฏธ๊ตญ์ฌํ
- ํ์จ
- ๋นํธ์ฝ์ธ
- cpp
- ํธ๋ ์ด๋
- ์๋ฆฌ์ดํธํ๋
- Today
- Total
์ถ์ ๊ณต์
[Spring] JPA, Entity, EntityManager ์ ๋๋ก ์ดํดํ๊ธฐ ๋ณธ๋ฌธ
๐ 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)๋ฅผ ๊น๊ฒ ๋ชฐ๋ผ๋ ์๋ฐ ์ฝ๋์ ๋ ์ง์คํ ์ ์์ด์!
ํด๋์ค | ํ ์ด๋ธ |
ํ๋ (๋ณ์) | ์ปฌ๋ผ (column) |
์ธ์คํด์ค (๊ฐ์ฒด) | ํ(row) |
โ๏ธ 3. MyBatis vs Hibernate (SQL Mapper vs ORM Framework)
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๋ฅผ ์ง์ ์ฌ์ฉํ ๋๋ ๋ ๋ช ์ ๋ง๋ฒ์ฌ๊ฐ ๋ฑ์ฅํด์.
- EntityManagerFactory (๋ง๋ฒ ์งํก์ด ๊ณต์ฅ):
- ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์์ ๋ฑ ํ๋๋ง ์กด์ฌํ๋ ์์ฃผ ํฐ ๊ณต์ฅ์ด์์.
- ์ด ๊ณต์ฅ์ ์ญํ ์ ์๋์ ๋์ฌ EntityManager(๋ง๋ฒ ์งํก์ด)๋ฅผ ๋ง๋๋ ๊ฒ์ด๋๋๋ค. ๊ณต์ฅ์ ๋น์ธ๊ณ ๋ง๋ค๊ธฐ ํ๋๋๊น ๋ฑ ํ๋๋ง ๋ง๋ค์ด์ ์ฐ๋ ๊ฑฐ์์.
- 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์ฐจ ์บ์ (Cache): ๋น๋ฐ ๋ ธํธ๋ ์์ ๊ธฐ์ต ์ฅ์(์บ์) ์ญํ ์ ํด์. ๋ง์ฝ ๋ง๋ฒ ์งํก์ด์๊ฒ ์๊น ๋ ธํธ์ ์ ์ด๋ user ์๋ฐํ๋ฅผ ๋ค์ ์ฐพ์๋ฌ๋ผ๊ณ (em.find(User.class, user.getId())) ํ๋ฉด, ์งํก์ด๋ ํฐ ๋์๊ด(DB)๊น์ง ๊ฐ์ง ์๊ณ ๋ ธํธ์์ ๋ฐ๋ก ์ฐพ์์ ์ค์. ์์ฒญ ๋น ๋ฅด๊ฒ ์ฃ ? (์ด๊ฑธ '1์ฐจ ์บ์'๋ผ๊ณ ๋ถ๋ฌ์.)
- ๋ณ๊ฒฝ ๊ฐ์ง (Dirty Checking): ๋ ์ ๊ธฐํ ๊ฑด, ๋ ธํธ์ ์ ํ ์๋ฐํ ์ ๋ณด(user)์ ๋ด์ฉ์ ์๋ฐ ์ฝ๋์์ ์ด์ง ๋ฐ๊พธ๋ฉด(user.setPassword("4321");), ๋ง๋ฒ ์งํก์ด๊ฐ ๊ทธ๊ฑธ ์๋์ผ๋ก ์์์ฐจ๋ ค์! ๊ทธ๋ฆฌ๊ณ ๋์ค์ ์ปค๋ฐํ ๋ ๋ฐ๋ ๋ด์ฉ๊น์ง ์์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์๊ด์ ๋ฐ์ํด ์ค๋ต๋๋ค. ๋ฐ๋ก "์ด๊ฑฐ ๋ฐ๊ฟ์ค!" ๋ผ๊ณ ์ฃผ๋ฌธํ ํ์๊ฐ ์์ด์!
- ์ฐ๊ธฐ ์ง์ฐ (Transactional write-behind): persist ์ฃผ๋ฌธ์ ํด๋, ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๋ผ๋ SQL ๋ช ๋ น์ ๋ ธํธ์๋ง ์ ์ด๋๊ณ ๋ฐ๋ก ๋ณด๋ด์ง ์์์. ๋ ธํธ์ ์ฌ๋ฌ ๋ณ๊ฒฝ ์ฌํญ(SQL ๋ช ๋ น)๋ค์ ๋ชจ์๋๋ค๊ฐ, ๋์ค์ ์ปค๋ฐํ ๋ ํ๊บผ๋ฒ์ ๋ณด๋ด์ฃ . (๋ง์น ์ฅ๋ฐ๊ตฌ๋์ ๋ฌผ๊ฑด์ ๋ด์๋๋ค๊ฐ ํ ๋ฒ์ ๊ณ์ฐํ๋ ๊ฒ๊ณผ ๊ฐ์์!)
- ์ง์ฐ ๋ก๋ฉ (Lazy Loading): (์กฐ๊ธ ์ด๋ ค์ด ๋ด์ฉ) ์๋ฐํ์ ์ฐ๊ฒฐ๋ ๋ค๋ฅธ ์ ๋ณด(์: ์๋ฐํ๊ฐ ์ด ๊ธ ๋ชฉ๋ก)๋ฅผ ์ฒ์๋ถํฐ ๋ค ๊ฐ์ ธ์ค์ง ์๊ณ , ์ง์ง ํ์ํ ๋ ๋ฑ! ๊ฐ์ ธ์ค๊ฒ ํ ์ ์์ด์. ์ด๊ฒ๋ ๋น๋ฐ ๋ ธํธ ๋๋ถ์ด์ฃ .
๐งผ 9. flush() vs commit()
๋น๋ฐ ๋ ธํธ(์์์ฑ ์ปจํ ์คํธ)์ ์ ํ ๋ณ๊ฒฝ ์ฌํญ(SQL ๋ช ๋ น)๋ค์ ์ธ์ ๊ฐ ์ง์ง ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์๊ด์ ๋ณด๋ด์ผ๊ฒ ์ฃ ? ์ด๋ flush()์ commit()์ด๋ผ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ด์.
- flush() (ํ๋ฌ์ - ๋ฌผ ๋ด๋ฆฌ๊ธฐ!):
- ๋ง๋ฒ ์งํก์ด๊ฐ ๋น๋ฐ ๋ ธํธ์ ์ง๊ธ๊น์ง ์์ธ SQL ๋ช ๋ น๋ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์๊ด์ ์ผ๋จ ๋ณด๋ด๋ ์์ ์ด์์.
- ํ์ง๋ง ์์ง ๋์๊ด ์ฌ์๊ฐ "๋ณ๊ฒฝ ์๋ฃ!" ๋์ฅ์ ์ฐ์ ๊ฑด ์๋์์. ๊ทธ๋์ ํน์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฉด ์์ง ๋กค๋ฐฑ(๋๋๋ฆฌ๊ธฐ)์ด ๊ฐ๋ฅํด์.
- flush()๋ฅผ ํ๋ค๊ณ ํด์ ํธ๋์ญ์ ์ด ๋๋๋ ๊ฑด ์๋์์!
- tx.commit() (์ปค๋ฐ - ํ์ !):
- "๋ชจ๋ ์์ ์ฑ๊ณต! ์ด์ ์ง์ง๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ํ ์ ์ฅํด์ค!" ๋ผ๊ณ ์ต์ข ํ์ ํ๋ ๋ช ๋ น์ด์์.
- ์ปค๋ฐ์ ํ๋ฉด, ๋ด๋ถ์ ์ผ๋ก flush()๊ฐ ์๋์ผ๋ก ๋จผ์ ํธ์ถ๋์ด์ ์์ง ๋ณด๋ด์ง ์์ SQL ๋ช ๋ น๋ค์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ณด๋ด์.
- ๊ทธ๋ฆฌ๊ณ ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ "๋ณ๊ฒฝ ์๋ฃ!" ๋์ฅ์ ๊ฝ! ์ฐ์ด์.
- ์ปค๋ฐ์ด ์๋ฃ๋๋ฉด ํธ๋์ญ์ ์ด ๋๋๊ณ , ๋ ์ด์ ๋กค๋ฐฑ(๋๋๋ฆฌ๊ธฐ)์ ํ ์ ์์ด์.
flush()์ 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์ ์ง์ง ์ ์ฅ |
'Web Dev > BackEnd' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] ์ฟผ๋ฆฌ ๋ฉ์๋! โ JPA์์ SQL ์์ด ์กฐํํ๊ธฐ (0) | 2025.05.09 |
---|---|
[Spring] Spring Data JPA โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ๊ฐํธํ๊ฒ ๋ง๋๋ ๊ธฐ์ (0) | 2025.05.09 |
[Spring] ๋ฐ์ดํฐ ๋ชจ๋ธ๋ง ์๋ฒฝ ๊ฐ์ด๋ (0) | 2025.05.02 |
[Spring] AOP ์๋ฒฝ ๊ฐ์ด๋ (0) | 2025.04.30 |
[Spring] DI์์ ์ธ๋ถ ์ค์ ์ฃผ์ ํ๊ธฐ: @ConfigurationProperties ํ์ฉ (0) | 2025.04.29 |