728x90
반응형
Lazy 란?
- 지연로딩이라고 한다.
언제쓸까?
- Member 객체안에 Team 객체가 있다고 생각해봅시다.
- Member 안에 team을 쓰는 경우가 드물다면?
- 보통은 Member 를 조회하면 안에 있는 Team도 같이 조회가 된다.
그렇게 되면 불필요한 연산이 추가가 되는 것이다. - Lazy를 사용하면 된다.
Lazy 예제
- FetchType.LAZY 를 써주면 된다.
- @ManyToOne(fetch = FetchType.LAZY)
Member class
@Entity
public class Member {
@Id //PK 설정
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "name", nullable = false, length = 100)
private String username;
// 프록시 객체로 조회한다.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
Main
System.out.println("====================================");
Member member = new Member9("Member");
em.persist(member);
Team team = new Team9();
team.setName("Team");
em.persist(team9);
member.setTeam(team);
em.flush();
em.clear();
// 프록시로 가져온다.
Member member = em.find(Member.class,member.getId());
// 팀에 대한 쿼리는 나가지 않는다 지연 로딩 때문에
System.out.println("member"+member.getTeam().getClass());
// 여기서 팀에대한 쿼리가 나간다.
// System.out.println("member"+member.getTeam().getName());
System.out.println("====================================");
결과
Hibernate:
select
member9x0_.MEMBER_ID as MEMBER_I1_19_0_,
member9x0_.TEAM_ID as TEAM_ID3_19_0_,
member9x0_.name as name2_19_0_
from
Member9 member9x0_
where
member9x0_.MEMBER_ID=?
설명
member 를 가져오는 쿼리만 발생 했다.
그 이유는 team에 LAZY 설정을 해주었기 때문이다.
위 예제에서 getTeam.getName() 부분에 주석처리를 제거 하면 Team 을 조회 하는 쿼리가 발생한다.
Eager 란?
만약 Team 과 멤버가 항상 같이 쓰인다면?
따로따로 호출해서 쓰는게 아니라 한번에 조회가 가능하다.
Eager 예제
- FetchType.EAGER를 써주면 된다.
- @ManyToOne(fetch = FetchType.EAGER)
@Entity
public class Member {
@Id //PK 설정
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "name", nullable = false, length = 100)
private String username;
// 프록시 객체로 조회한다.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
결과
left outer join 으로 한번에 가져왔다.
Hibernate:
select
member9x0_.MEMBER_ID as MEMBER_I1_19_0_,
member9x0_.TEAM_ID as TEAM_ID3_19_0_,
member9x0_.name as name2_19_0_,
team9x1_.TEAM_ID as TEAM_ID1_26_1_,
team9x1_.name as name2_26_1_
from
Member9 member9x0_
left outer join
Team9 team9x1_
on member9x0_.TEAM_ID=team9x1_.TEAM_ID
where
member9x0_.MEMBER_ID=?
member9class lazy.Team9
프록시와 즉시로딩 주의점
즉시로딩 적용시 예상치 못한 SQL 이 발생한다.
- -join이 너무 많이 나간다.
- find 할 경우 Eager 10개를 걸면 join이 10개가 나간다.
- 실무에서 는 지연로딩을 써야 한다.
즉시로딩은 JPQL에서 N+1 문제를 발생 시킨다.
- 1 개의 쿼리를 수행 했지만 추가로 N개의 쿼리가 나간다.
- em.find는 최적화 해서 가져오지만
jpql은 그대로SQL 로번역이 된다. - N+1 이 되는과정
- Member 만 select 한다. (1)
- Member 만 select 했지만 Team 이 즉시로딩으로 되어 있으니
- Team을 또 쿼리로 가져온다.(N+1)
정리
- XtoOne 은 기본이 즉시 로딩
- XtoMany 는 기본이 지연로딩이다.
- 모든 연관관계에 지연로딩을 쓰자.
- 실무에서 즉시 로딩을 사용하지 말자.
- 참고로 JPQL 에서 fetch join을 쓰면 N+1 문제를 해결 할 수 있다.
728x90
반응형
'DataBase > JPA' 카테고리의 다른 글
[JPA] 값타입 (0) | 2021.08.22 |
---|---|
[JPA] CASCADE (0) | 2021.08.22 |
[JPA] 프록시 (0) | 2021.08.11 |
[JPA] @MappedSuperclass (0) | 2021.08.09 |
[JPA] 고급 매핑1: 상속관계 맵핑 (0) | 2021.08.08 |
댓글