경주장
프록시와 연관관계 관리 본문
프록시
Member를 조회할 때 Team도 함께 조회해야 할까?
프록시 기초
- em.find() vs em.getReference()
- em.find(): 데이터베이스를 통해서 실제 엔티티 객체 조회
- em.getReference(): 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회
프록시 특징
- 실제 클래스를 상속 받아서 만들어짐
- 실제 클래스와 겉 모양이 같다.
- 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용하면 됨(이론상)
- 프록시 객체는 실제 객체의 참조(target)를 보관
- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출
Member member = em.getReference(Member.class, “id1”);
member.getName();
즉시 로딩과 지연 로딩
지연 로딩 (Lazy loading)을 사용해서 프록시로 조회 하자
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne(fetch = FetchType.LAZY) //**
@JoinColumn(name = "TEAM_ID")
private Team team;
..
}
-> Member를 조회할때 team을 조회할 필요가 없다!
FetchType.Lazy
- Member를 로딩할때 team은 프록시로 로딩한다.
- 실제 Team을 사용하는 (Team의 Method를 호출, 필드를 조회) 시점에 DB조회가 발생한다.
- 쿼리가 두번 나간다.
FetchType.Eager
- Member를 로딩할때 team도 실제 객체가 바로 로딩
- Member와 Team테이블을 조인한 쿼리가 한번 나간다.
프록시와 즉시로딩 주의
- 가급적 지연 로딩만 사용(특히 실무에서)
- 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
- 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.
- @ManyToOne, @OneToOne은 기본이 즉시 로딩 -> LAZY로 설정
- @OneToMany, @ManyToMany는 기본이 지연 로딩
FetchType.Lazy를 쳐발쳐발하자
영속성 전이: CASCADE
- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들도 싶을 때
- 예: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장.
e.g. 부모를 영속성 컨텍스트에 넣을때 자식도 함께 넣기
@Entity
public class Parent{
@Id @GeneratedValue
@Column("parent_id")
private Long id;
@OneToMany(mappedBy("parent"), casecade = CasecadeType.PERSIST)
private List<chile> children = new ArrayList<>();
...
}
@Entity
public class Child{
@Id @GeneratedValue
@Column("child_id")
private Long id;
@ManyToOne
@JoinedColumn("parent_id")
private Parent parent;
...
}
고아 객체(orphan)
고아 객체 제거: 부모 엔티티와 연관관계가 끊어진 자식 엔티티 를 자동으로 삭제
'JPA' 카테고리의 다른 글
JPQL - 기본 문법 (0) | 2022.01.05 |
---|---|
값 타입 (0) | 2022.01.05 |
고급 매핑 (0) | 2022.01.04 |
다양한 연관관계 매핑 (0) | 2022.01.04 |
연관관계 매핑 기초 (0) | 2022.01.04 |