Life Developer
인생 개발자
[JPA]즉시로딩(EAGER)의 문제점

 

@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)를 사용하는것이 좋다.

 

지연로딩 때려박고 프록시 초기화하면 된다.

  Comments,     Trackbacks