JPA #8 ํ๋ก์์ ์ง์ฐ๋ก๋ฉ (join fetch)
by JiwonDev๐ ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค.
Member๋ Team์ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
Member๋ฅผ ์กฐํํ ๋ Team๋ ํ๋ฒ์ ๊ฐ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ ธ์ค๋๊ฒ ํจ์จ์ ์ธ ๊ฒฝ์ฐ๋ ์๊ณ
๋จผ์ Member๋ง ์กฐํํด๋๊ณ , ๋์ค์ ํ์ํ ๋ Team์ ๊ฐ์ ธ์ค๋๊ฒ ๋ ํจ์จ์ ์ธ ๊ฒฝ์ฐ๋ ์์ ๊ฒ์ด๋ค.
์ํฉ์ ๋ฐ๋ผ DB ์ฟผ๋ฆฌ๊ฐ ๋ค๋ฅด๊ฒ ๋๊ฐ๋๋ก ์ต์ ํํ๋๊ฒ ์ข์๋ฐ, ์ด๋ JPA์์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ ์์๊น?
๐ ํ๋ก์ em.getReference()
๊ทธ๋์ JPA์์๋ ํ๋ก์๋ฅผ ์ ๊ณตํ๋ค.
- em.find()๋ ์ค์ ์ํฐํฐ๋ฅผ ๋ฐํํ๋ค๋ฉด
- em.getReference()๋ ๊ฐ์ง ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
ํ๋ก์๋ ์ค์ ํด๋์ค๋ฅผ ์์๋ฐ์์ ๋ง๋ ๊ฐ์ฒด๋ก, ์ค์ ๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ์ ๊ฐ์ง๊ณ ์๋ค.
ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ์ ์ผ๋ถ๋ง ๊ฐ์ ธ์ฌ ์ ์๋ค. ๊ฐ์ ธ์ค์ง ์์ ๋ฐ์ดํฐ๋ ์ฌ์ฉํ๋์์ ๊น์ง DB์ฟผ๋ฆฌ๋ฅผ ๋ฆ์ถ๋ค.
// id ๊ฐ๋ง ์กฐํํ๊ณ , ๋๋จธ์ง ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ์ง ์๋๋ค.
Member member = em.getReference(Member.class, member.getId());
member.getId(); // ์ด๋ฏธ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ ์ฌ์ฉ. DB์ฟผ๋ฆฌ X
member.getName(); // ๊ฐ์ ธ์จ์ ์ด ์๋ ๋ฐ์ดํฐ. ์ด ์์ ์ ์๋ก์ด DB์ฟผ๋ฆฌ ๋ฐ์
์ต์ด์ getReference๋ฅผ ํธ์ถํ๋ ์์ ์๋, ์ค์ ๊ฐ์ฒด์ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ง์๊ณ ๊ทธ๋ฅ ํ๋ก์๋ง ๋ง๋ ๋ค.
โจ ๋จ ์ด๋ฏธ ์์์ฑ ์ปจํ ์คํธ์ ์ค์ ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด ๊ตณ์ด ํ๋ก์๋ฅผ ๋ง๋ค์ง ์๊ณ ์ค์ ์ํฐํฐ๋ฅผ ๋ฐํํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ค์ ๊ฐ์ด ํ์ํ ๋ ์์์ฑ ์ปจํ ์คํธ๋ฅผ ํตํด DB์์ ์กฐํํด์ ์ค์ ๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
์ฐธ๊ณ ๋ก ๋น์์, ์ค์์ ์ํ(detach)์ผ ๋ ํ๋ก์๋ฅผ ์ด๊ธฐํํ๋ฉด ์์ธ(hibernate.LazyInitializationException)๊ฐ ๋ฐ์ํ๋ค.
์ฆ, ํ๋ก์ ๊ฐ์ฒด๋ ๋ฑ 1๋ฒ๋ง ์ด๊ธฐํ๋๊ณ ๊ณ์ ์ฌ์ฉ๋๋ค. ์ค๊ฐ์ ์ค์ ๊ฐ์ฒด๋ก ๋ฐ๋๋๊ฒ ์๋๋ค.
์ฌ์ฉํ๋ ์์ ์ DB์์ ์กฐํํ๊ณ [ ํ๋ก์ ๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ ] ์ ์ค์ ๊ฐ์ฒด๊ฐ ๋ค์ด๊ฐ๋ ๊ฑฐ๋ค.
โ ํ๋ก์๋ ์ธ์ ์ฌ์ฉ๋ ์ง ๋ชจ๋ฅธ๋ค. ํ์ ๋น๊ต๋ instance of
์ํฐํฐ์ ํ์ ๋น๊ตํ ๋์๋ ๋ฐ๋์ instance of๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
JPA์์๋ ๊ฐ์ฒด์ ํ์ ์ (==)๋ก ๋น๊ตํด์๋ ์๋๋ค. ํ๋ก์๋ ์๋ณธ ๊ฐ์ฒด๋ฅผ ๋น๊ตํ๋ฉด ํ์ ์ด ๊ฐ์๋ False๊ฐ ๋ฐํ๋๋ค.
๋ค๋ง ํ์ ๋ง๊ณ ๊ฐ์ฒด์ ๋์ผ์ฑ์ (==)๋ก ๋น๊ตํด๋ ๋๋ค.
- getReference()๋ ์ด๋ฏธ ์์์ฑ ์ปจํ ์คํธ์ ๊ฐ์ ธ์จ ์ค์ ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด, ํ๋ก์๊ฐ ์๋ ์ค์ Entity๋ฅผ ๋ฐํํ๋ค.
- ๋์ผ์ฑ์ ๋ง์ถ๊ธฐ ์ํด์ ํธ์ถ ์์์ ๋ฐ๋ผ em.find()๋ ํ๋ก์๋ฅผ ๋ฐํํ ์๋ ์๋ค.
// ์ค์ ๐ถEntity๊ฐ ๋ฐํ๋จ
Member.findMember = entityManager.find(Member.class, member1.getId());
// ์์์ฑ ์ปจํ
์คํธ์ Entity๊ฐ ์์. ํ๋ก์๊ฐ ์๋ ์ค์ ๐ถEntity๊ฐ ๋ฐํ๋จ
Member proxyMember = entityManager.getReference(Member.class, member1.getId());
// True, ๐ถEntity == ๐ถEntity
System.out.println(porxyMember == findMember);
// โจProxy ๊ฐ์ฒด๊ฐ ๋ฐํ๋จ
Member proxyMember = entityManager.getReference(Member.class, member1.getId());
// ์ค์ Entity๊ฐ ๋ฐํ๋์ด์ผํ์ง๋ง, ์กฐํํด๋ณด๋ฉด โจProxy ๊ฐ์ฒด๊ฐ ๋ฐํ๋จ
Member.findMember = entityManager.find(Member.class, member1.getId());
// True, โจProxy == โจProxy
System.out.println(porxyMember == findMember);
๊ทธ๋์ JPA์์๋ ์๋์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํด์ค๋ค.
// ํ๋ก์ ์ธ์คํด์ค์ ์ค์ ๊ฐ์ฒด์ฐธ์กฐ ์ด๊ธฐํ ์ฌ๋ถ true / false
entityMangerFactory.PersistenceUnitUtil.isLoaded(Object proxyEntity)
// ํด๋์ค ์ด๋ฆ ํ์ธ (ํด๋์ค ๋ช
์ผ๋ก ํ๋ก์ ์ฌ๋ถํ์ธ)
entity.getClass().getName()
์ฌ์ฉํ ์ผ์ ๊ฑฐ์ ์์ง๋ง, ์ฌ์ฉ์ฌ๋ถ์ ์๊ด์์ด ํ๋ก์์ ์ค์ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๊ฐ์ ๋ก ์ด๊ธฐํํ๊ณ ์ถ๋ค๋ฉด ์๋์ ๊ฐ๋ค.
org.hibernate.Hibernate.initialize(proxyEntity);
๐ ๋ค๋ง getReference()๋ฅผ ์ธ ์ผ์ ๊ฑฐ์ ์๋ค.
ํ๋ก์์ ๋์์ ์ดํดํ๊ธฐ์ํด ์ด๋ฐ ๋ฉ์๋๋ ์๋ค๋ ๊ฑธ ์๋ ค์ค ๊ฒ์ด๋ค.
์ค์ ์ฌ์ฉ์ getReference()๋ฅผ ์ฐ์ง์๊ณ , ์ ๋ ธํ ์ด์ ์ ์ต์ ์ ํตํ ์ง์ฐ๋ก๋ฉ์ ์ฌ์ฉํ๋ค.
๐ ์ฆ์๋ก๋ฉ๊ณผ ์ง์ฐ๋ก๋ฉ
๋ฒ๊ฑฐ๋กญ๊ฒ getRefernce()๋ก ํ๋ก์๋ฅผ ๊ด๋ฆฌํ ํ์์์ด, ์๋์ ๊ฐ์ดํ๋ฉด ๋๋ค.
@Entity
public class Member {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
์ฟผ๋ฆฌ๋ฅผ ์ฐ์ด๋ณด๋ฉด em.find()๋ก ์กฐํํ๋ฉด ์ค์ ๊ฐ์ฒด๊ฐ ์๋ ํ๋ก์๊ฐ ๋ฐํ๋์์์ ์ ์ ์๋ค.
์ฆ ์์์ ์ค๋ช ํ๊ฒ๊ณผ ๋๊ฐ์ด ์ค์ ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ ์์ (getTeam)์์ ์์์ฑ ์ปจํ ์คํธ์ DB์ฟผ๋ฆฌ๊ฐ ๋ ๋ผ๊ฐ๊ฒ๋๊ณ , ํ๋ก์์ ์ฐธ์กฐ๊ฐ ์ด๊ธฐํ๋๋ค.
๋ฐ๋๋ก Member์ Team์ ํญ์ ๊ฐ์ด ์ฌ์ฉํด์, ํ๋ฒ์ ๋ชจ๋ ๊ฐ์ ธ์ค๊ณ ์ถ๋ค๋ฉด ์ฆ์๋ก๋ฉ์ผ๋ก ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
JPA ๊ตฌํ์ฒด(ํ์ด๋ฒ๋ค์ดํธ)๋ ์ฆ์๋ก๋ฉ์ ์ฌ์ฉํ๋ฉด ์กฐ์ธ์ ์ด์ฉํด์ ํ๋์ SQL๋ฌธ์ ์ต๋ํ ๋ง์ ํ ์ด๋ธ์ ๊ฐ์ ธ์จ๋ค.
@Entity
public class Member {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
โ ๋๋๋ก์ด๋ฉด ๋ชจ๋ ์ฐ๊ด๊ด๊ณ๋ฅผ ์ง์ฐ ๋ก๋ฉ(LAZY)๋ก ์ฌ์ฉํ์.
๋ชจ๋ ์ฐ๊ด ๊ด๊ณ๋ ๋๋๋ก์ด๋ฉด Lazy๋ก ์ค์ ํด์ ์ฌ์ฉํ์.
- @ManyToOne, @OneToOne โก ์ฆ์๋ก๋ฉ(Eager)๋ฅผ ๊ธฐ๋ณธ ๊ฐ์ผ๋ก ์ ๊ณต
- @OneToMany, @ManyToMany โก ์ง์ฐ๋ก๋ฉ(Lazy)๋ฅผ ๊ธฐ๋ณธ ๊ฐ์ผ๋ก ์ ๊ณต
์์ ์ฟผ๋ฆฌ๋ฌธ์ ๋ณด๋ฉด ์๊ฒ ์ง๋ง, JPA ํน์ฑ์ ์ฆ์๋ก๋ฉ์ ์ ํ ์์ํ์ง ๋ชปํ SQL๋ฌธ์ ๋ฐ์์ํจ๋ค.
๋ง์ฝ ์ฐธ์กฐ๊ฐ 10๊ฐ๋ผ๋ฉด, Member ํ๋ฒ ์กฐํ๋ก ํ ์ด๋ธ 10๊ฐ๋ฅผ ์กฐ์ธํ๋ ์ ์ ๋๊ฐ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ํ ์ฆ์๋ก๋ฉ์ JPQL์ ์ฌ์ฉํ ๋ N+1 ๋ฌธ์ ๋ฅผ ์ผ์ผํค๊ธฐ ์ฝ๋ค.
// 1. JPQL์ ์ฌ์ฉํ๋ฉด ์ฆ์ flush๋์ด Member๋ฅผ DB์์ ๊ฐ์ ธ์จ๋ค
em.createQurey("select m from Member m", Member.class);
// 2. ๊ทธ๋ฐ๋ฐ Member์์ ์๋ Team์ด ์ฆ์๋ก๋ฉ์ด๋ค. ๊ฐ์ ๋ฐ๋ก ๊ฐ์ ธ์์ผํ๋ค.
// 3. ๊ฐ๊ฐ์ Member๋ ๋ค๋ฅธ Team ๊ฐ์ ๊ฐ์ง๋ค. ๋ง์ฝ Member๊ฐ 10๊ฐ๋ฉด Team ์ฟผ๋ฆฌ๋ 10๊ฐ๊ฐ ๋ฐ์ํ๋ค.
// SQL : select * from Team where TEAM_ID = xxx.. ์ฟผ๋ฆฌ๊ฐ ๋ฉค๋ฒ ๊ฐ์๋งํผ ๋ฐ์.
@Entity
public class Member {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn
private Team team;
}
์ฆ ๋ ์ฟผ๋ฆฌ1๋ฒ์ ๋ ๋ ธ๋๋ฐ, ์ค์ ์ฟผ๋ฆฌ๋ 1+N๋ฒ (Team์ ์กฐํํ๋ ์ฟผ๋ฆฌ N๊ฐ)๊ฐ ๋ฐ์ํ๋ ๊ฐํ์ด ๋ฐ์ํ ์ ์๋ค.
์ง์ฐ๋ก๋ฉ (Lazy)๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฐ ์ผ์ด ์๋ค. Team์ ์ฌ์ฉํ๋ ์๊ฐ๊น์ง ๋ฏธ๋ฃจ๋ค๊ฐ ์ฌ์ฉํ๋ ์์ ์ ์ฟผ๋ฆฌ ํ๋๋ง ๋๊ฐ๋ค.
๋ง์ฝ Member์ Team์ ํจ๊ป ๊ฐ์ ธ์ค๊ณ ์ถ๋ค๋ฉด JPA์ fetch join์ ์ด์ฉํ๋๋ก ํ์.
์ด๋ SQL๋ฌธ์ ์กด์ฌํ๋ ๋ฌธ๋ฒ์ ์๋๊ณ , ์ฐ๊ด๋ ์ํฐํฐ(์ปฌ๋ ์ )์ ๊ฐ์ด ์กฐํํ ๋ค์ ๊ฐ์ฒด ํ๋์ set์ผ๋ก ์ฐ๊ฒฐํ๋ ๋ฐฉ๋ฒ.
// join fetch ์กฐ์ธ๊ฒฝ๋ก
em.createQuery("select m from Member m join fetch m.team", Member.class)
ํจ์น ์กฐ์ธ์ ํตํด ์ฐ๊ด๋ Team์ ์ด๋ฏธ ์์์ฑ ์ปจํ ์คํธ๋ก ๊ฐ์ ธ์์ผ๋ฏ๋ก, ์ดํ ํธ์ถํ๋๋ผ๋ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
List<Member> list =
em.createQuery(jpql "select m from Member m join fetch m.team", Member.class).getResultList();
for(Member m : list){
System.out.println(m.getTeam().getName()); // LAZY ๋ก๋ฉ ๋ฐ์ ์ํจ
}
๊ทธ ์ธ ์ํฐํฐ ๊ทธ๋ํ ์ ๋ ธํ ์ด์ ์ด๋ ๋ฐฐ์น์ฌ์ด์ฆ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๊ธดํ๋ฐ, ์ด๋ ๋์ค์ ์์๋ณด๋๋ก ํ์.
๐ ์์์ฑ ์ ์ด, @OneToMany( casecade= ~ ) ์ต์
์ผ๋จ ์คํฌ๋ถํฐ ํ์๋ฉด, ์์์ฑ ์ ์ด๋ ์ฐ๊ด๊ด๊ณ๋ฅผ ๋งคํํ๋ ๊ฒ๊ณผ ์๋ฌด๋ฐ ๊ด๊ณ๊ฐ ์๋ค.
์ํฐํฐ๋ฅผ ์์ํ ํ ๋, ์ฐ๊ด๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ ํจ๊ป ์์ํํ๋ ํธ์๋๊ตฌ์ด๋ค.
- Parent์ Child์ ๋ผ์ดํ์ฌ์ดํด์ด ๊ฐ์์, ํ๊บผ๋ฒ์ ํต์ผ๋ก ์ ์ฅ/ ์ญ์ ํ๊ณ ์ถ์ ๋ ์ฌ์ฉ.
- ์์ ์๊ฐ 1๊ฐ (Parent - Child) ์์๋ง ์ฌ์ฉํ๊ณ , ๋ง์ฝ Child๋ฅผ ์ฐ๋ ๊ณณ์ด ์ฌ๋ฌ ๊ณณ์ด๋ผ๋ฉด ์ ๋ ์ฐ๋ฉด ์๋๋ค.
์ ๋ฉ๋ฆฌ์ ์์ ์ ํ๋๋ฐ, ๋ด ์ํฐํฐ์ ๋ณ๊ฒฝ์ด ์ ํ๋๋ฉด ํฐ์ผ๋๋ค.
์ํฐํฐ๋ฅผ ์์ํ ํ ๋, ์ฐ๊ด๋ ์ํฐํฐ๋ ํจ๊ป ์์ํํ๋ ํธ์๋๊ตฌ์ด๋ค. ์ข ๋ฅ๋ ์๋์ ๊ฐ์ด 6๊ฐ๊ฐ ์กด์ฌํ๋ค.
- ALL ๋ชจ๋ ์ ์ฉ - ๋ชจ๋ ์ ํ๋ฅผ ์ ์ฉ
- PERSIST ์์๋ง - ์ ์ฅํ ๋์๋ง ์ ํ ์ฌ์ฉ
* cascade๋ก ์์ํ๋ฅผ ์๋ํ๋ ๊ฐ์ฒด๊ฐ ์ด๋ฏธ DB์ ํค๊ฐ์ด ์กด์ฌํ๋ค๋ฉด PersistentObjectException ๊ฐ ๋ฐ์ํ๋ค.
๋ค๋ง ์ 2๊ฐ์ง๋ง ์์ฃผ ์ฌ์ฉํ๊ณ , ์๋ 4๊ฐ์ง๋ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋๋ค.
- REMOVE ์ญ์ ๋ง - ๋ถ๋ชจ๋ฅผ ์ญ์ ํ๋ฉด ๋ฐ์ ์์๋ ๋ชจ๋ ์ญ์ ๊ฐ ์ ํ๋จ
- MERGE ๋ณํฉ๋ง - ํธ๋์ญ์ ์ด ์ข ๋ฃ๋๊ณ ์ค์์ ์ํ์์ ์ํฐํฐ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋, ๋ถ๋ชจ๊ฐ merge()๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ
- RERESH ๋ฆฌํ๋ ์๋ง - ์ํฐํฐ๋ฅผ ์๋ก ๊ณ ์น ๋, ์ด ํ๋์ ๋ณด์ ๋ ์ํฐํฐ๋ ์๋ก๊ณ ์นจํจ.
- DETACH ์ค์์๋ง - ๋ถ๋ชจ๊ฐ detach()๋ก ์ค์์์ํ๊ฐ ๋๋ฉด, ์์๋ ๋ชจ๋ ์ค์์ํ๋จ.
์ด๋ ์์ ๋ฅผ ๋ณด๋ฉด ์ฝ๊ฒ ์ดํดํ ์ ์๋ค. ์๋ ์ฝ๋๋ฅผ ๋ณด์
@Entity
public class Child {
@ManyToOne
@JoinColumn("PARENT_ID")
private Parent parent;
public void setParent(Parent parent) {
this.parent = parent;
}
}
@Entity
public class Parent {
@OneToMany(mappedBy = "parent")
private List<Child> childList = new ArrayList<>();
public void addChild(Child child) {
childList.add(child);
child.setParent(this); // ์ฐ๊ด๊ด๊ณ ์ค์
}
}
์ด ์ฝ๋๋ฅผ ๊ธฐ์กด์ JPA๋ก ์ฌ์ฉํ๋ฉด ์๋์ ๊ฐ์ด ํ๋ํ๋ persist() ํด์ค์ผ ํ๋ค.
Child childOne = new Child();
Child childTwo = new Child();
Parent parent = new Parent();
parent.addChild(childOne);
parent.addChild(childTwo);
entityManager.persist(parent);
entityManager.persist(childOne);
entityManager.persist(childTwo);
์ด๋ฅผ Parent์์ ์๋์ ๊ฐ์ด Cascade๋ฅผ ALL๋ก ์ค์ ํด์ฃผ๋ฉด
@Entity
public class Parent {
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> childList = new ArrayList<>();
...
}
parent ๊ฐ ์ฐธ์กฐํ๋ ๋ชจ๋ ๊ฐ์ฒด๋ ํจ๊ป ์์ํ๋๋ค.
Child childOne = new Child();
Child childTwo = new Child();
Parent parent = new Parent();
parent.addChild(childOne);
parent.addChild(childTwo);
// cascade = ALL ์ด๋ผ์ parent ๋ด๋ถ์์๋ ๋ชจ๋ child๋ ํจ๊ป ์์ํ๋จ.
entityManager.persist(parent);
// entityManager.persist(childOne);
// entityManager.persist(childTwo);
์๋ฅผ ๋ค์ด ์ฃผ๋ฌธ๊ณผ ๋ฐฐ๋ฌ์ด ์์ ๋, [์ฃผ๋ฌธ์ด ๋ฐฐ๋ฌ์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ถ๋ค๋ฉด] ์๋์ ๊ฐ์ด ์ค์ ํด์ค ์ ์๋ค.
๋ฌผ๋ก ์ด๋ ๋น์ฆ๋์ค ์ํฉ์ ๋ฐ๋ผ์ ๋ค๋ฅด๋ค. ์ฃผ๋ฌธ์ด ์ญ์ ๋์ด๋ ๋ณ๋์ ๋ฐฐ๋ฌ ๊ธฐ๋ก๋ง ๋จ๊ธฐ๊ณ ์ถ์ ์๋ ์์ผ๋๊น.
// ์ด์ Order์ Delivery๋ ๊ฐ์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ณต์ ํ๋ค.
@OneToMany(mappedBy = "parent", cascade = ALL)
private List<Delivery> Deliverys = new ArrayList<>();
๐ @OneToMany(orphanRemoval = true) , ๊ณ ์ ๊ฐ์ฒด ์ญ์
๋ง์ด ์ข ์ฌํ๋ฐ, ๋ถ๋ชจ ์ํฐํฐ์ ๊ด๊ณ๊ฐ ๋์ด์ง ์์ ์ํฐํฐ๋ฅผ ์ญ์ ํ๋ ๊ธฐ๋ฅ์ด๋ค.
- ๋ฐ๋์ ์ฐธ์กฐํ๋ ๊ณณ์ด ํ๋์ผ ๋ ์ฌ์ฉํด์ผํ๋ค. GC์ฒ๋ผ ์ฐธ์กฐ ์ถ์ ํด์ฃผ๋ ๊ธฐ๋ฅ์ ์๋ค.
- @OneToOne, @OneToMany๋ง ๊ฐ๋ฅํ๋ฉฐ ํน์ ์ํฐํฐ๊ฐ ๊ฐ์ธ ์์ (ํ ๊ฐ์ฒด๋ง ์ฐธ์กฐ)์ผ ๋ ์ฌ์ฉํ๋ค.
* ์ฐธ๊ณ ๋ก Parent๋ฅผ ํต์ผ๋ก ์ญ์ ํ๋ฉด cascade = REMOVE ์ฒ๋ผ ๋์ํ๋ค. ๋ชจ๋ ์์ ๊ฐ์ฒด๋ฅผ ์ญ์ ํ๋ค.
@Entity
public class Parent {
@OneToMany(mappedBy = "parent", orphanRemoval = true) // ์ค์
private List<Child> childList = new ArrayList<>();
...
}
Parent parent1 = em.find(Parent.class, id);
parent1.getChildren().remove(0); // Parent์์ Child์ ์ฐ๊ด๊ด๊ณ๋ฅผ ๋์๋ค.
// orphanRemoval = true์ธ ๊ฒฝ์ฐ, ๋ฐ๋ก Child๊ฐ DB์์ ์ญ์ ๋จ
DELETE FROM Child WHERE ID=0
โ ๊ฟํ (๋ถ๋ชจ๊ฐ ์์๊ฐ์ฒด์ ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ)
์ฐธ๊ณ ๋ก ์๋์ ๊ฐ์ด ALL + orphanRemoval์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ถ๋ชจ๊ฐ์ฒด๊ฐ ์์๊ฐ์ฒด์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์์ ํ ๊ด๋ฆฌํ ์ ์๋ค.
์ฆ ์ด๋ ๊ฒํ๋ฉด ๋ถ๋ชจ ๊ฐ์ฒด๋ง Repository์ ์ฐ๊ฒฐ๋์ด์์ผ๋ฉด ์์ ๊ฐ์ฒด์ฉ Repository๋ ๊ตฌํํ ํ์๊ฐ ์๋ค.
โก ์ด๋ ๋๋ฉ์ธ ์ฃผ๋ ์ค๊ณ(DDD)์์ Aggregate Root ๊ฐ๋
์ ๊ตฌํํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค.
Repository๋ ์ค์ง Aggregate Root๋ง ์ฐ๊ฒฐ๋์ด์๊ณ , Root๊ฐ ๋ชจ๋ ๊ฐ์ฒด์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๋๋ก ๋ง๋ค ์ ์๋ค.
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
'๐ฑBackend > JDBC & JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JPA 10 # ๊ฐ์ฒด ์ฟผ๋ฆฌ ์ธ์ด, JPQL (0) | 2021.11.16 |
---|---|
JPA #9 ๊ฐ ํ์ , ์ปฌ๋ ์ , ์๋ฒ ๋๋ ํ์ (0) | 2021.11.09 |
JPA #7 ๊ณ ๊ธ ๋งคํ (์์ ๊ด๊ณ) (0) | 2021.11.09 |
JPA #6 ๋ค์ํ ์ฐ๊ด๊ด๊ณ ๋งคํ (1:N, N:1, N:N) (0) | 2021.11.09 |
JPA #5 ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์ ๋ฌธ์ ์ , ์ฐ๊ด ๊ด๊ณ ๋งคํ (0) | 2021.11.09 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev