-
[JPA] ํ๋ก์์ ์ฐ๊ด๊ด๊ณ ๊ด๋ฆฌBack-end/JPA 2022. 4. 28. 00:12
๐ ํ๋ก์
- ํ๋ก์ ๊ฐ๋ ์ Hibernate์ ๊ตฌํ๋์ด ์๋ ๊ฒ์ด๋ค.
- JPA ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ก Hibernate๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํ๋ก์๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด๋ค.
EntityManager์ find() : ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํตํด ์ค์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์กฐํ
EntityManager์ getReference() : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์กฐํ๋ฅผ ๋ฏธ๋ฃจ๋ ๊ฐ์ง(ํ๋ก์) ์ํฐํฐ ๊ฐ์ฒด ์กฐํ
โถ๏ธ ํ๋ก์๊ฐ ํ์ํ ์์ ์ํฉ
์์ ๊ฐ์ ๊ตฌ์กฐ๋ก ์ค๊ณ๊ฐ ๋์ด์์ ๋ 'Member๋ฅผ ์กฐํํ ๋ Team๋ ํจ๊ป ์กฐํํด์ผ ํ ๊น?' ๋ผ๋ ์๋ฌธ์์ ํ๋ก์๋ ์ฌ์ฉ๋๊ฒ ๋์๋ค.
Member์ ํ๋๋ง ์กฐํํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ Team์ ์กฐ์ธํด์ ๊ฐ์ ธ์ค์ง ์์๋ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
โถ๏ธ ํ๋ก์์ ํน์ง1
- ์ค์ ํด๋์ค๋ฅผ ์์ ๋ฐ์์ ๋ง๋ค์ด์ง๋ค.
- ์ค์ ํด๋์ค์ ๊ฒ ๋ชจ์์ด ๊ฐ๋ค.
- ํ๋ก์ ๊ฐ์ฒด๋ ์ค์ ๊ฐ์ฒด์ ์ฐธ์กฐ(์์์ target)๋ฅผ ๋ณด๊ดํ๋ค.
- ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ๋ฉด ํ๋ก์ ๊ฐ์ฒด๋ ์ค์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
*์ถ๊ฐํ ๋ด์ฉ
Hibernate๊ฐ ์๋์ผ๋ก Entity๋ฅผ ์์ ๋ฐ์ Proxy ํด๋์ค๋ฅผ ์์ฑํด์ค๋ค.
Entity ํด๋์ค์ default ์์ฑ์๊ฐ ํ์ํ ์ด์ ์ ๋ฆฌํด๋๊ธฐ!
โถ๏ธ ํ๋ก์ ๊ฐ์ฒด์ ์ด๊ธฐํ
= ์์์ฑ ์ปจํ ์คํธ๋ฅผ ํตํด DB ์กฐํ ํ ์ค์ Entity๋ฅผ ์์ฑํ๋ ๊ฒ
์์ ์ํฉ
//์์ ์ฝ๋ Member member = entityManager.getReference(Member.class, "id1"); member.getName();
- ์์์ EntityManager์ getReference()๋ก ํ๋ก์ ์ํฐํฐ๋ฅผ ์กฐํํ๋ค.
- member.getName(); ์ด ์คํ๋ ๋ ๋ฐ์ํ๋ ์ํฉ์ ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ๋ค.
(1) getName() ์ฝ๋๊ฐ ์คํ๋๋ฉด, ํ๋ก์ ๊ฐ์ฒด๋ ์ค์ ๊ฐ์ฒด์ getName()์ ํธ์ถํด์ผ ํ๋ฏ๋ก,
(2) ์์์ฑ ์ปจํ ์คํธ์ ์ด๊ธฐํ ์์ฒญ์ ํ๋ค. (์ด๋๋ MemberProxy์ target์ด ์ค์ฒด ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ์ง ์๊ณ ์์ผ๋ฏ๋ก Null์ด๊ธฐ ๋๋ฌธ์)
(3), (4) ์์์ฑ ์ปจํ ์คํธ์์ DB์ ์กฐํ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค ์ค์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ ์์ฑํ๊ณ , MemberProxy์ target์ ์์ฑํ ์ค์ Entity๋ฅผ ์ฐ๊ฒฐํด์ค๋ค.
(5) ์ค์ ๊ฐ์ฒด์ getName() ํธ์ถํ๋ค.
โถ๏ธ ํ๋ก์์ ํน์ง2
- ํ๋ก์ ๊ฐ์ฒด๋ ์ฒ์ ์ฌ์ฉํ ๋ ํ ๋ฒ๋ง ์ด๊ธฐํ๊ฐ ์ด๋ฃจ์ด์ง๋ค.
- ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ ๋, ํ๋ก์ ๊ฐ์ฒด๊ฐ ์ค์ ์ํฐํฐ๋ก ๋ณ๊ฒฝ๋๋ ๊ฒ์ด ์๋๋ผ, ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํตํด์ ์ค์ ์ํฐํฐ์ ์ ๊ทผ์ด ๊ฐ๋ฅํด์ง ๊ฒ์ด๋ค. (์์ ์์์์ target ํ๋)
- ํ๋ก์ ๊ฐ์ฒด๋ ์๋ณธ ์ํฐํฐ๋ฅผ ์์๋ฐ์ผ๋ฏ๋ก ๊ฐ์ฒด ํ์
์ฒดํฌ์ ์ฃผ์ํด์ผ ํ๋ค.
- ํ๋ก์ or ์ํฐํฐ๊ฐ ๋์ด์ฌ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ == ๋น๊ต ์คํจ, instance of ์ฌ์ฉ
- ์์์ฑ ์ปจํ ์คํธ์ ์ฐพ๋ ์ํฐํฐ๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ค๋ฉด, getReference()๋ฅผ ํธ์ถํด๋ ํ๋ก์๊ฐ ์๋ ์ค์ ์ํฐํฐ๋ฅผ ๋ฐํํ๋ค.
- ํ๋ก์๋ ์์์ฑ ์ปจํ ์คํธ๋ฅผ ํตํด ๊ฐ์ฒด ์ด๊ธฐํ๋ฅผ ํ๊ธฐ ๋๋ฌธ์, ์์์ฑ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ค์์ ์ํ์ธ ๊ฒฝ์ฐ, ํ๋ก์ ์ด๊ธฐํ๋ฅผ ์์ฒญํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. (Hibernate๋ org.hibernate.LazyInitializationException ์์ธ๋ฅผ ๋ฐ์์ํด)
*์ถ๊ฐํ ๋ด์ฉ
==๊ณผ instance of์ ์ฐจ์ด์ ์?
โถ๏ธ ํ๋ก์ ํ์ธํ๋ ๋ฐฉ๋ฒ
- ํ๋ก์ ์ธ์คํด์ค์ ์ด๊ธฐํ ์ฌ๋ถ ํ์ธ
- PersistenceUnitUtil.isLoaded(Object entity)
- ํ๋ก์ ํด๋์ค ํ์ธ
- entity.getClass().getName()
- ํ๋ก์ ๊ฐ์ ์ด๊ธฐํ
- org.hibernate.Hibernate.initialize(entity);
- But, JPA ํ์ค์ ๊ฐ์ ์ด๊ธฐํ๊ฐ ์๊ณ , ํด๋น ์ํฐํฐ์ ํ๋์ getter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. (ํ๋ก์ ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ, ์ด๊ธฐํ๊ฐ ๋๊ธฐ ๋๋ฌธ์)
๐ ์ฆ์ ๋ก๋ฉ๊ณผ ์ง์ฐ ๋ก๋ฉ
โถ๏ธ ์ง์ฐ ๋ก๋ฉ(LAZY)
= JPA์ Entity์์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ฒ ํ๋ ์ค์
์์ ์ํฉ
//์ํฐํฐ @Entity public class Member { @Id @GeneratedValue private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Team team; ... }
//์กฐํ Member member = entityManager.find(Member.class, 1L); // A Team team = member.getTeam(); team.getName(); // B
A) Member ์ํฐํฐ๋ DB๋ฅผ ํตํด ์กฐํํ์ง๋ง, Team์ ํ๋ก์ ๊ฐ์ฒด๋ก ๊ฐ์ ธ์จ๋ค.
B) ์ค์ Team ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ์์ ์ ์ด๊ธฐํ๋ฅผ ์ํํ๋ค. ์ด๋ DB๋ฅผ ํตํด ์กฐํํ๋ฏ๋ก ์ฟผ๋ฆฌ๊ฐ ์ํ๋๋ค.
โถ๏ธ ์ฆ์ ๋ก๋ฉ(EAGER)
= JPA์ Entity์์ ํ๋ก์ ๊ฐ์ฒด ์ฌ์ฉํ์ง ์๋ ์ค์
์์ ์ํฉ - Member์ Team์ ํจ๊ป ์์ฃผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
@Entity public class Member { @Id @GeneratedValue private Long id; private String name; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "team_id") private Team team; ... }
//์กฐํ Member member = entityManager.find(Member.class, 1L); // A
A) Member๋ฅผ ์กฐํํ ๋ Join์ ์ฌ์ฉํด DB์์ Team๋ ํจ๊ป ์กฐํํด์จ๋ค.
๐ ํ๋ก์์ ์ฆ์๋ก๋ฉ ์ฃผ์
- ์ฆ์ ๋ก๋ฉ์ ์ค์ ํ๋ฉด ํ๋ฒ์ ์กฐํํด์์ผ ํ๋ฏ๋ก ์์ํ์ง ๋ชปํ SQL์ด ๋ฐ์ํ ์ ์์ด ๊ฐ๊ธ์ ์ง์ฐ ๋ก๋ฉ๋ง ์ฌ์ฉํ๋๋ก ํ๋ค.
- ์ฆ์ ๋ก๋ฉ์ ์ค์ ํ ๋ค JPQL์ ์ฌ์ฉํด ์ํฐํฐ๋ฅผ ์กฐํํ๊ฒ ๋๋ฉด, ์ฆ์ ๋ก๋ฉ์ผ๋ก ์ค์ ๋ ์ํฐํฐ๋ฅผ ํจ๊ป ์กฐํํด์ค๊ธฐ ์ํด N+1 ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
- N+1 = 1๋ฒ์ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ ๊ฐ์ด N๊ฐ ์ผ ๋, N๋ฒ์ ์ฟผ๋ฆฌ๊ฐ ์ถ๊ฐ ์ํ๋๋ ๊ฒ
- ์ฐ์ JPQL์ SQL๋ก ๋ฒ์ญ๋์ด ์คํ๋๊ณ , JPA์์ ์ต์ ํ๋ฅผ ์์ผ์ฃผ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ด๋ค.
- ์์) ์์ ์์์ธ Member์ Team์ ์ํฉ์ด๊ณ Member๊ฐ N๊ฐ ์กด์ฌํ ๋, JPQL๋ก Member๋ฅผ ์กฐํํ๋ฉด, N๊ฐ์ Member ์ํฐํฐ๊ฐ ๋ฐํ๋๊ณ , ๊ฐ Member์ ์ฆ์ ๋ก๋ฉ์ผ๋ก ์ค์ ๋ Team๋ ์กฐํํด์ค๊ธฐ ์ํด Team์ ์กฐํํ๋ N๋ฒ์ ์ฟผ๋ฆฌ๊ฐ ์ถ๊ฐ๋ก ์ํ๋๋ ์ํฉ์ด ๋๋ ๊ฒ์ด๋ค.
๐ ์์์ฑ ์ ์ด: CASCADE
์ฌ์ฉํ๋ ์ด์
- ํน์ ์ํฐํฐ๋ฅผ ์์ ์ํ๋ก ๋ง๋ค ๋ ์ฐ๊ด๋ ์ํฐํฐ๋ ํจ๊ป ์์ ์ํ๋ก ๋ง๋ค๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค.
๐ ๊ณ ์ ๊ฐ์ฒด
- ๊ณ ์ ๊ฐ์ฒด ์ ๊ฑฐ : ๋ถ๋ชจ ์ํฐํฐ์ ์ฐ๊ด๊ด๊ณ ๋์ด์ง ์์ ์ํฐํฐ๋ฅผ ์๋์ผ๋ก ์ญ์ ํ๋ค.
์์ ์ํฉ
//๊ณ ์ ๊ฐ์ฒด ์ค์ orphanRemoval = true //์ฐ๊ด๊ด๊ณ ๋๊ธฐ Parent parent = entityManager.find(Parent.class, 1L); parent.getChildren().remove(0); //์์ ์ํฐํฐ๋ฅผ ์ปฌ๋ ์ ์์ ์ ๊ฑฐ //DELETE ์ฟผ๋ฆฌ ์ํ DELETE FROM CHILD WHERE ID = ?
- ์์ฒ๋ผ ๊ณ ์ ๊ฐ์ฒด ์ค์ ์ ํ๋ฉด, @OneToMany ๊ด๊ณ์ ๋ฆฌ์คํธ ์ปฌ๋ ์ ์์ ํด๋น ์ํฐํฐ๋ฅผ ์ ๊ฑฐํ๊ธฐ๋ง ํด๋, DB์ DELETE ์ฟผ๋ฆฌ๊ฐ ์๋์ผ๋ก ๋๊ฐ ํด๋น ์ํฐํฐ๊ฐ DB ํ ์ด๋ธ์์ ์ญ์ ๋๋ค.
โถ๏ธ CASCADE์์ ์ฐจ์ด์
- CASCADE : ๋ถ๋ชจ ์ํฐํฐ๊ฐ ์ญ์ ๋ ๋ ์์ ์ํฐํฐ๋ค๋ ํจ๊ป ์ญ์
- ๊ณ ์ ๊ฐ์ฒด ์ค์ : CASCADE ๊ธฐ๋ฅ + ์ฐ๊ด๊ด๊ณ๊ฐ ๋์ด์ง๊ธฐ๋ง ํด๋ ์์ ์ํฐํฐ ์ญ์
โถ๏ธ ์ฃผ์ํ ์
- ๋ถ๋ชจ ์ํฐํฐ์์์ ์ฐธ์กฐ๊ฐ ์ ๊ฑฐ๋ ์ํฐํฐ๋ ๋ค๋ฅธ ๊ณณ์์ ์ฐธ์กฐํ์ง ์๋ ๊ณ ์ ๊ฐ์ฒด๋ก ํ๋จํ๊ณ ์ญ์ ํ๊ฒ ๋๋ค.
- ์ฐธ์กฐํ๋ ๊ณณ์ด ํ๋์ผ ๋ ์ฌ์ฉํด์ผ ํ๋ค.
๐ ์์์ฑ ์ ์ด + ๊ณ ์ ๊ฐ์ฒด
- CascadeType.ALL + orphanRemoval=true 2๊ฐ์ง ์ต์ ์ ๋ชจ๋ ํ์ฑํํ๋ฉด, ๋ถ๋ชจ ์ํฐํฐ๋ฅผ ํตํด ์์์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค.
- ๋๋ฉ์ธ ์ฃผ๋ ์ค๊ณ์ Aggregate Root ๊ฐ๋ ์ ๊ตฌํํ ๋ ์ ์ฉํ๋ค.
*์ถ๊ฐํ ๋ด์ฉ
DDD์ Aggregate Root ๊ฐ๋ ์ด ๋ฌด์์ธ๊ฐ?
@OneToOne์ ๋์ ์ํฐํฐ(PK๊ฐ ์๋ ํ ์ด๋ธ)๋ FetchType.LAZY๋ก ์ค์ ํด๋ ์กฐํ ์ ์ง์ฐ ๋ก๋ฉ์ด ์ ์ฉ๋์ง ์๋๋ฐ ๊ทธ ์ด์ ๋?
'Back-end > JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPA] ๊ฐ ํ์ (0) 2022.04.28 [JPA] ์์๊ด๊ณ ๋งคํ๊ณผ @MappedSuperclass (0) 2022.04.27 [JPA] ์ฐ๊ด๊ด๊ณ ๋งคํ (0) 2022.04.14 [JPA] ์ํฐํฐ ๋งคํ (0) 2022.04.11 [JPA] ๋ฑ์ฅ ๋ฐฐ๊ฒฝ, ์ฌ์ฉ ์ด์ , ๊ฐ๋จ ๊ตฌ๋ ๋ฐฉ์ (0) 2022.03.31