✅ fetch = FetchType.LAZY ✅ fetch = FetchType.EAGER
다음 두가지 경우가 있다고 해보자
public void printUserAndTeam(String memberId) {
Member member = em.find(Member.class, memberId);
Team team = member.getTeam();
System.out.println("회원 이름: " + member.getUsername());
System.out.println("소속팀: " + team.getName());
}
public void printUser(String memberId) {
Member member = em.find(Member.class, memberId);
Team team = member.getTeam();
System.out.println("회원 이름: " + member.getUsername());
}
회원과 팀을 항상 함께 출력한다면 문제가 되지 않지만
회원만 출력하는 경우에는 팀까지 불러올 필요가 없으므로 낭비가 생긴다.
이를 해결하기 위해 jpa에서 프록시와 지연로딩을 지원한다.
Member와 Team을 자주 함께 사용하지 않는 경우
실제 사용하는 경우에만 초기화를 하여 낭비를 줄임
Member select 쿼리는 있고 Team을 사용하는 경우에만 Team select 쿼리 날림
1 (+1)
@Entity
public class Member extends BaseEntity{
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member1 = new Member();
member1.setUsername("user1");
member1.setTeam(team);
em.persist(member1);
em.flush();
em.clear();
Member m = em.find(Member.class, member1.getId());
System.out.println("m = " + m.getTeam().getClass()); // proxy(가짜)
m.getTeam().getName(); // 초기화 (이때 쿼리 날라감)
Member와 Team을 자주 함께 사용하는 경우
굳이 지연 로딩 (LAZY)을 사용하여 쿼리를 2번에 나눠 날릴 필요가 없음
@Entity
public class Member extends BaseEntity{
...
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member1 = new Member();
member1.setUsername("user1");
member1.setTeam(team);
em.persist(member1);
em.flush();
em.clear();
Member m = em.find(Member.class, member1.getId()); // Member 와 Team 을 join 하여 한번에 다 가져옴
System.out.println("m = " + m.getTeam().getClass()); // proxy(가짜)가 아니라 team.class(진짜)로 뜸
m.getTeam().getName();
🔥 가급적 지연 로딩(LAZY)만 사용 (실무)
한방에 가져와야 할 경우에 JPQL - join fetch 사용함
@ManyToOne, @OneToOne : 기본이 즉시 로딩(EAGER) -> 지연 로딩(LAZY)으로 해줘야 함
@OneToMany, @ManyToMany : 기본이 지연 로딩(LAZY)