์ฐ๊ด๊ด๊ณ๊ฐ ์กด์ฌํ๋ ์ํฐํฐ๋ฅผ ์กฐํ ์, ์ฐ๊ด๋ ์ํฐํฐ๋ก ํจ๊ป ์กฐํํด์์ผ ํ๋์ง์ ๋ํด์ ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
์ฐ๊ด๋ ์ํฐํฐ๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ํ๋ฒ์ ๊ฐ์ด ์กฐํํ๋ ๊ฒ์ด ์ข์๊ฒ์ด๊ณ ,
ํจ๊ป ์ฌ์ฉํ๋ ์ผ์ด ๊ฑฐ์ ๋ฐ์ํ์ง ์๋๋ค๋ฉด ์กฐํํ์ง ์๋๊ฒ์ด ์ฑ๋ฅ์ ์ข์ ๊ฒ์ ๋๋ค.
JPA์์๋ ์์ ๊ฐ์ ์ํฉ๋ค์ ๋๋นํ์ฌ, ์ํฐํฐ๊ฐ ์ค์ ์ฌ์ฉ๋ ๋๊น์ง ๋ฐ์ดํฐ๋ฒ ์ด์ค ์กฐํ๋ฅผ ์ง์ฐํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
์ด ๋ฐฉ๋ฒ์ ์ง์ฐ ๋ก๋ฉ(lazy loading)์ด๋ผ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ง์ฐ ๋ก๋ฉ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํด, ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํฉ๋๋ค.
EntityManager์ ๋๊ฐ์ง ๋ฉ์๋
ํ๋ก์์ ๋ํด ์์ธํ ์์๋ณด๊ธฐ ์ ์ EntityManger์์ ์ ๊ณตํ๋ ๋๊ฐ์ง ๋ฉ์๋์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
find : ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํตํด์ ์ค์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์กฐํํฉ๋๋ค.
getReference : ํ๋ก์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ค. (๊ฐ์ฒด๋ฅผ ์ค์ ์ฌ์ฉํ๋ ์์ ๊น์ง ๋ฐ์ดํฐ๋ฒ ์ด์ค ์กฐํ๋ฅผ ๋ฏธ๋ฃน๋๋ค.)
์ด๋ ์ค์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์์
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private long id;
private String name;
public void setName(String name) {
this.name = name;
}
public void logic(){
System.out.println("์๋
!");
}
}
find() ์ฌ์ฉ
Member member = new Member();
member.setName("shin");
em.persist(member);
em.flush();
em.clear();
System.out.println("======================");
Member find = em.find(Member.class, member.getId());
System.out.println("find.getId() : "+find.getId());
System.out.println("find.getName() : "+find.getName());
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
getReference() ์ฌ์ฉ
Member member = new Member();
member.setName("shin");
em.persist(member);
em.flush();
em.clear();
System.out.println("======================");
Member find = em.getReference(Member.class, member.getId());
System.out.println("find.getId() : "+find.getId());
System.out.println("find.getName() : "+find.getName());
id ์ฌ์ฉ๊น์ง๋ ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ์ง ์๋ค๊ฐ, name์ ์ฌ์ฉํ๋ ์๊ฐ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ์์ต๋๋ค.
์ค์ํ ๊ฒ์ ๋ฐ๋์ ํ๋์ ๋ํ ์ฌ์ฉ์ด ์๋๋๋ผ๋ ํ๋ก์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค๋ฉด ์กฐํ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
Member member = new Member();
member.setName("shin");
em.persist(member);
em.flush();
em.clear();
System.out.println("======================");
Member find = em.getReference(Member.class, member.getId());
System.out.println("find.getId() : "+find.getId());
System.out.println("logic ํธ์ถ!!!");
find.logic();
์์ฒ๋ผ ํ๋ก์ ๊ฐ์ฒด์ ํ๋์ ์ ํ ์ฐ๊ด์๋ ๋ฉ์๋๋ฅผ ์คํ์ํค๋๋ผ๋ ์๋์ ๊ฐ์ด ์กฐํ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ ๊ฒ์ ์ ์ ์์ต๋๋ค.
ํ๋ก์์ ํน์ง
- ํ๋ก์ ๊ฐ์ฒด๋ ์ฒ์ ์ฌ์ฉํ ๋ ํ ๋ฒ๋ง ์ด๊ธฐํ ํฉ๋๋ค. (์ฌ์ฉ์ ๊ธฐ์ค์ ๋ฉ์๋ ํธ์ถ์ ๋๋ค.)
- ํ๋ก์ธ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํ ํ ๋, ํ๋ก์ ๊ฐ์ฒด๊ฐ ์ค์ ์ํฐํฐ๋ก ๋ฐ๋๋ ๊ฒ์ด ์๋๋๋ค. ์ด๊ธฐํ ํ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํตํด ์ค์ ์ํฐํฐ์ ์ ๊ทผ์ด ๊ฐ๋ฅํด์ง๋ ๊ฒ์ ๋๋ค.
- ํ๋ก์ ๊ฐ์ฒด๋ ์๋ณธ ์ํฐํฐ๋ฅผ ์์๋ฐ์ต๋๋ค. ๋ฐ๋ผ์ ํ์ ์ฒดํฌ์ ์ฃผ์ํด์ผ ํฉ๋๋ค. (== ๋น๊ต ๋์ ์ instanceof ์ฌ์ฉ)
- ์์์ฑ ์ปจํ ์คํธ์ ์ฐพ๋ ์ํฐํฐ๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ค๋ฉด, em.getReference()๋ฅผ ํธ์ถํด๋ ์ค์ ์ํฐํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
- ์์์ฑ ์ปจํ ์คํธ์ ๋์์ ๋ฐ์ ์ ์๋ ์ค์์ ์ํ์ผ ๋, ํ๋ก์๋ฅผ ์ด๊ธฐํํ๋ฉด ์๋ฌ(LazyInitializationException)๊ฐ ๋ฐ์ํฉ๋๋ค.
5๋ฒ์ ์์
Member refMember = em.getReference(Member.class, member1.getId());
em.detach(refMember);
refMember.getUsername();//์์ธ ๋ฐ์
LazyInitializationException: could not initialize proxy [jpa.jpa.Member#1] - no Session
ํ๋ก์ ์ด๊ธฐํ ์ฌ๋ถ ํ์ธ
EntityManagerFactory์์ ์ ๊ณตํ๋ PersistenceUnitUtil์ isLoaded ๋ฉ์๋๋ฅผ ํตํด ํ์ธํ ์ ์์ต๋๋ค.
Member member = new Member();
member.setName("shin");
em.persist(member);
em.flush();
em.clear();
System.out.println("======================");
Member find = em.getReference(Member.class, member.getId());
System.out.println("isLoaded : " + emf.getPersistenceUnitUtil().isLoaded(find));
find.logic();
System.out.println("isLoaded : " + emf.getPersistenceUnitUtil().isLoaded(find));
ํ๋ก์์ ์๋ณ์
ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ฒ์ ์ฌ์ฉํ ๋, ํ๋ก์๊ฐ ์ด๊ธฐํ(DB์์ ์ค์ ์ํฐํฐ ์กฐํ)๋๋ค๊ณ ํ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์์ธ๊ฐ ํ๋ ์์ต๋๋ค.
๋ฐ๋ก ์๋ณ์์ ๋๋ค.
์ํฐํฐ๋ฅผ ํ๋ก์๋ก ์กฐํํ ๋, ์๋ณ์(PK) ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๋๋ฐ, ํ๋ก์ ๊ฐ์ฒด๋ ์ด ์๋ณ์ ๊ฐ์ ๋ณด๊ดํฉ๋๋ค.
Member member = em.getReference(Member.class, 1L); //์๋ณ์ ๋ณด๊ด
member.getId(); //์ด๊ธฐํ๋์ง ์์
member.getName();//์ด๊ธฐํ
ํ๋ก์ ๊ฐ์ฒด๋ ์๋ณ์ ๊ฐ์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์, ์๋ณ์ ๊ฐ์ ์กฐํํ๋ ๊ฒฝ์ฐ์๋ ํ๋ก์ ๊ฐ์ฒด๊ฐ ์ด๊ธฐํ๋์ง ์์ต๋๋ค.
๊ทธ๋ผ ๋ค์์ ์ด๋จ๊น์?
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Getter
@Setter
public class Member extends BaseEntity{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private Long age;
public Long getId() {
return age;
}
}
Member member = new Member();
member.setAge(12L);
em.persist(member);
em.flush();
em.clear();
Member reference = em.getReference(Member.class, 1L);
System.out.println(reference.getId());
System.out.println(reference.getAge());
System.out.println(reference.getId());
์ฝ๋๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด, getId()๋ฅผ age๋ฅผ ๋ฐํํ๋๋ก ๋ง๋ค์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ๊ฒฐ๊ณผ๋ ์์ ์ธ๋ก ๋์ํฉ๋๋ค.
ํ๋ก์์์๋ getId()๋ฅผ ์ฐ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ์ ์ํ๋์ง๊ฐ์ ๋ฌด์ํ๊ณ id๋ง ๋ฐํํ๋๋ก ๋ง๋ค์์ต๋๋ค.
์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด ๋ถ๋ถ์ ํ๋ก์ ๊ฐ์ฒด์ ์ฑ๋ฅ ์ต์ ํ์ ๊ด๋ จ์ด ๋์ด ์์ต๋๋ค.
id์ ๊ฒฝ์ฐ ์ด๋ฏธ ์๊ณ ์๊ธฐ ๋๋ฌธ์, ์ต๋ํ ์ด๊ธฐํ๋ฅผ ํ์ง ์์ผ๋ ค๊ณ ๋ ธ๋ ฅํ๋ ๊ฒ์ด์ง์.
JPA์์๋ ์ด๋ฐ ์ ๋๋ฌธ์ getter์ ๊ฒฝ์ฐ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ง์ถ์ด์ผ ํฉ๋๋ค.
ํ๋ก์ ๊ฐ์ ์ด๊ธฐํ
Hibernate.initialize(entity)
์ง์ฐ๋ก๋ฉ๋ ํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ฃผ์์
ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ํ๋์ ๋ํ ์ ๋ณด๊ฐ ํ์ํ๋ค๋ฉด ๋ฐ๋์ ๋ฉ์๋๋ฅผ ํตํด์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
ํ๋์ ์ง์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ์๋ ํญ์ null์ด ๋ฐํ๋ฉ๋๋ค.
์ด๋ ๊ฒ ์ค์ ํ ์ด์ ๋ ์ ํํ๋ ๋ชจ๋ฅด๊ฒ ์ผ๋ ํด๋น ๊ด๋ จํด์๋ ์ ์ ๋ค๋ฅธ ๊ฒ์๊ธ(https://ttl-blog.tistory.com/277)๋ ํจ๊ป ์ฐธ๊ณ ํด์ฃผ์ธ์
๋ฌธ์ ๊ฐ ๋๋ ์ฝ๋
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Member father;
@OneToMany(mappedBy = "father")
private List<Member> child = new ArrayList<>();
public void setFather(Member father) {
this.father = father;
}
public void setName(String name) {
this.name = name;
}
public void fieldLogic(){
System.out.println("์๋น ์ด๋ฆ(field) : " + father.name);
}
public void methodLogic(){
System.out.println("์๋น ์ด๋ฆ(getter) : " + father.getName());
}
}
๋ค์๊ณผ ๊ฐ์ Member๊ฐ ์์ต๋๋ค.
Member father = new Member();
Member child = new Member();
father.setName("์๋น ");
child.setFather(father);
em.persist(father);
em.persist(child);
em.flush();
em.clear();
Member member = em.find(Member.class, child.getId());
member.fieldLogic();
member.methodLogic();
์ ์ฝ๋์ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์์ ๊ฐ์ด ํ๋์ ์ง์ ์ ๊ทผํ๋ ๊ฒ์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ์ง ๋ชปํฉ๋๋ค.
์ถ๊ฐ๋ก ์ด๊ธฐํ ๋ ๊ฒฝ์ฐ๋ผ๋ ํ๋์ ์ง์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ์๋ null์ด ์กฐํ๋ฉ๋๋ค.
ํด๋น ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
Member father = new Member();
Member child = new Member();
father.setName("์๋น ");
child.setFather(father);
em.persist(father);
em.persist(child);
em.flush();
em.clear();
Member member = em.find(Member.class, child.getId());
member.methodLogic();
member.fieldLogic();
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Reference
[์๋ฐ ORM ํ์ค JPA ํ๋ก๊ทธ๋๋ฐ - ๊น์ํ]
'๐๏ธ Spring > JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPA] ์์์ฑ ์ ์ด(CASCADE)์ ๊ณ ์ ๊ฐ์ฒด (0) | 2021.12.15 |
---|---|
[JPA] ์ฆ์ ๋ก๋ฉ๊ณผ ์ง์ฐ ๋ก๋ฉ ( + PersistentBag) (0) | 2021.12.15 |
[JPA] @AssocicationOverride - ์ฐ๊ด๊ด๊ณ(์ธ๋ ํค ์ปฌ๋ผ๋ช ) ์ฌ์ ์ (0) | 2021.12.15 |
[JPA] ํ๋์ ์ปฌ๋ผ ๋งคํ - @Embedded (์๋ฒ ๋๋ ํ์ ๋งคํ) (0) | 2021.12.15 |
[JPA] @MappedSuperclass (0) | 2021.12.15 |