๐ฅ JPA์ ์์ ์ํ(Persistent State) ์ ๋ฆฌ
JPA๋ฅผ ์ ๋๋ก ์ดํดํ๋ ค๋ฉด, **“์์ ์ํ(Persistent State)”**๋ฅผ ์ค์ฌ์ผ๋ก ์ฌ๊ณ ํด์ผ ํฉ๋๋ค.
์ด ๊ฐ๋
์ ์ ํํ ์ดํดํ๋ฉด, ๋ค์๊ณผ ๊ฐ์ ํค์๋๋ค์ด ์ ๋ถ ํ๋๋ก ์ฐ๊ฒฐ๋ฉ๋๋ค:
- orphanRemoval
- flush()
- dirty checking (๋ณ๊ฒฝ ๊ฐ์ง)
- merge()
JPA ์ํฐํฐ ์๋ช ์ฃผ๊ธฐ 4๋จ๊ณ
JPA๋ ์ํฐํฐ ๊ฐ์ฒด์ ์ํ๋ฅผ ํฌ๊ฒ ๋ค์ 4๋จ๊ณ๋ก ๋๋๋๋ค.
์ํ ์ค๋ช ์์
| ๋น์์ (Transient) | EntityManager์ ๋ฑ๋ก๋์ง ์์ ์ํ | new Member() |
| ์์ (Persistent) | EntityManager๊ฐ ๊ฐ์ฒด๋ฅผ ์ถ์ (tracking)ํ๋ฉฐ DB์ ์ฐ๊ฒฐ๋ ์ํ | em.persist(member) |
| ์ค์์ (Detached) | ํ๋ ์์์ด์์ง๋ง, EntityManager์์ ๋ถ๋ฆฌ๋ ์ํ | ํธ๋์ญ์ ์ข ๋ฃ ํ, em.detach(member) |
| ์ญ์ ์์ (Removed) | ์ญ์ ์์ฝ ์ํ. ํธ๋์ญ์ ์ปค๋ฐ ์ DELETE ์คํ ์์ | em.remove(member) |
์์ ์ํ(Persistent)๋?
EntityManager๊ฐ ํด๋น ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ๋ฉฐ, ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ ํ๊ณ DB ๋ฐ์๊น์ง ์ฑ ์์ง๋ ์ํ
ํน์ง
- ๋ณ๊ฒฝ ๊ฐ์ง(Dirty Checking) ์๋
- flush() ์์ ์ ์๋ SQL ์คํ
- orphanRemoval, cascade ๋ฑ JPA ๊ธฐ๋ฅ์ด ์ ์ ์๋
- ๋์ผ ํธ๋์ญ์ ๋ด์์ ๊ฐ์ฒด ์ผ๊ด์ฑ ์ ์ง (1์ฐจ ์บ์ ํ์ฉ)
์์๋ก ์ดํดํ๊ธฐ
Member m = new Member("ํ๊ธธ๋"); // โ ๋น์์
em.persist(m); // โ
์์ ์ํ๋ก ์ ํ
m.setName("์๊บฝ์ "); // dirty checking ๋์
em.flush(); // → UPDATE member SET name='์๊บฝ์ ' ...
Dirty Checking (๋ณ๊ฒฝ ๊ฐ์ง)
์์ ์ํ์ ๊ฐ์ฒด๋ ๋ด๋ถ ๊ฐ์ด ๋ฐ๋๋ฉด JPA๊ฐ ์๋์ผ๋ก SQL UPDATE๋ฅผ ์์ฑํฉ๋๋ค.
flush() ์์ ์ ๋น๊ตํ์ฌ, ๋ฌ๋ผ์ง ํ๋๋ง ์
๋ฐ์ดํธํฉ๋๋ค.
๐ก ์ด๊ฒ์ด JPA๊ฐ “SQL์ ์ ์จ๋ ๋๋” ์ด์ ์ค ํ๋์ ๋๋ค.
flush()
EntityManager๊ฐ ๊ด๋ฆฌ ์ค์ธ ๋ณ๊ฒฝ ์ฌํญ์ DB์ ๊ฐ์ ๋ฐ์ํฉ๋๋ค.
์๋ ํธ์ถ ์์
- ํธ๋์ญ์ ์ปค๋ฐ ์
- JPQL ์คํ ์
- em.flush() ์ง์ ํธ์ถ
flush๋ "์ฐ๊ธฐ ๋๊ธฐํ(sync)"๊ณ , ์์ง ํธ๋์ญ์ ์ข ๋ฃ๋ ์๋๋๋ค.
orphanRemoval = true
๋ถ๋ชจ์์ ์์ ์ปฌ๋ ์ ์์๋ฅผ **์ ๊ฑฐ(remove)**ํ๋ฉด,
JPA๊ฐ ์ด๋ฅผ ๊ณ ์(orphan) ๊ฐ์ฒด๋ก ๊ฐ์ฃผํด ์๋์ผ๋ก DELETEํฉ๋๋ค.
@OneToMany(mappedBy = "parent", cascade = ALL, orphanRemoval = true)
private List<Child> children = new ArrayList<>();
parent.getChildren().remove(child); // → child๋ DB์์ ์๋ ์ญ์ ๋จ
โ์ฃผ์:
- setChildren(new ArrayList<>())์ฒ๋ผ ์ปฌ๋ ์
์์ฒด๋ฅผ ๋ฐ๊พธ๋ฉด,
JPA๊ฐ ์ถ์ ํ๋ ์ปฌ๋ ์ ์ฐธ์กฐ๊ฐ ๋๊ฒจ์ ์์ธ(JpaSystemException) ๋ฐ์ ๊ฐ๋ฅ - ์ฌ๋ฐ๋ฅธ ๋ฐฉ์์:
- parent.getChildren().clear(); parent.getChildren().addAll(newList);
merge()
์ค์์(Detached) ๊ฐ์ฒด๋ฅผ ๋ค์ ์์ ์ํ๋ก ์ ํํ ๋ ์ฌ์ฉํฉ๋๋ค.
Member detached = ...; // ํธ๋์ญ์
์ด ๋๋ ํ์ ๊ฐ์ฒด
Member merged = em.merge(detached); // ์๋ก์ด ์์ ๊ฐ์ฒด ๋ฐํ
โ์ฃผ์: merge()๋ ์๋ ๊ฐ์ฒด๋ฅผ ์์ํํ๋ ๊ฒ ์๋๋ผ, ๋ณต์ฌํ ์ ๊ฐ์ฒด๋ฅผ ์์ํํฉ๋๋ค.
๐ง ์ข ํฉ ์์ฝ
๊ธฐ๋ฅ ์์ ์ํ ํ์ ์ค๋ช
| dirty checking | โ | ๊ฐ ๋ณ๊ฒฝ ์ ์๋ UPDATE |
| flush() | โ | DB ๋ฐ์ (SQL ์คํ ์์ ) |
| orphanRemoval | โ | ์ปฌ๋ ์ ์์ ์ ๊ฑฐ๋ ์์ ์๋ DELETE |
| merge() | โ | Detached → Persistent๋ก ๋ณต์ |
โจ ๋ง๋ฌด๋ฆฌ ์ ๋ฆฌ
- JPA์์ ๋ชจ๋ ํต์ฌ ๋์์ “์์ ์ํ”๋ฅผ ๊ธฐ์ค์ผ๋ก ์ด๋ค์ง๋ค.
- persist()๋ก ๊ฐ์ฒด๋ฅผ ์์ํํ๋ฉด, ์ดํ์๋ SQL์ ๋ชฐ๋ผ๋ ๋ ๋งํผ JPA๊ฐ ์์์ ์ฒ๋ฆฌํด์ค๋ค.
- orphanRemoval์ด๋ cascade ๊ฐ์ ์ต์ ๋ ์์ ์ํ์ผ ๋๋ง ์ ํจํ๋ค.
- ๋ฌด์ฌ์ฝ ์ปฌ๋ ์ ์ set()์ผ๋ก ๊ต์ฒดํ๋ฉด ์์์น ๋ชปํ ์์ธ๊ฐ ํฐ์ง ์ ์์ผ๋ ์กฐ์ฌํ์.
'๊ณต๋ถ > Spring Boot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| JPA Specification (0) | 2025.03.28 |
|---|---|
| @SQLRestriction("IS_DELETED = 0") (0) | 2025.02.10 |
| @SQLRestriction ์ด๋ ธํ ์ด์ : ์ฌ์ฉ๋ฒ๊ณผ ์ฅ๋จ์ ๋ถ์ (1) | 2024.11.20 |
| [Java] Spring Boot - JPA @PrePersist, @PreUpdate (0) | 2024.11.20 |
| Spring Boot Webflux๋ (0) | 2024.01.12 |