@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="TEAM_ID")
private Team team;
처럼 즉시로딩하면 문제점이 생긴다.
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println(" ================================== ");
tx.commit(); //이시점에 DB 쿼리가 날라감
이럴 경우 select 쿼리가 2번 나가게 된다.
select * from member 한번 나가고, 나가는 도중 team이 즉시로딩이네? 라고 판단되어
또다시 select * from team 쿼리가 나가게 되는것이다.
그냥 .find 같은 경우에는 pk를 찍어서 가져오는거기 때문에 JPA가 걍 알아서 해주는데 이건 아니다.
이거 심각한 문제다.
아래 경우엔 team select를 2번하게 된다.
Team team = new Team();
team.setName("teamA");
Team team2 = new Team();
team2.setName("teamB");
Member member1 = new Member();
member1.setUserName("member1");
member1.setTeam(team);
Member member2 = new Member();
member2.setUserName("member1");
member2.setTeam(team2);
em.persist(team);
em.persist(team2);
em.persist(member1);
em.persist(member2);
em.flush();
em.clear();
// Member m = em.find(Member.class, member1.getId());
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println(" ================================== ");
tx.commit(); //이시점에 DB 쿼리가 날라감
물론 LAZY로 설정하고
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
for(Member m:members){
System.out.println("m.getTeam().getName() = " + m.getTeam().getName());
}
이렇게 해줘도 뭐 foreach로 team 정보 가져올때마다 team을 계속 부르는건 매한가지지만 대안이있다.
1. fetch 조인 (한방쿼리) - List<Member> members = em.createQuery("select m from Member m join fetch m.team", Member.class).getResultList();
2. 엔티티그래프(어노테이션) -모름
3. 배치사이즈 -모름
일단 3가지가 있다고 한다.
실무에서는 그냥 무조건 지연로딩(LAZY)를 사용하는것이 좋다.
지연로딩 때려박고 프록시 초기화하면 된다.