Life Developer
인생 개발자
[JAP]fetch 조인 - 한방쿼리

fetch가 무엇인가?

 

join 할때 한방에 다 가져오는 전략. fetch 전략!

 

Entity만들때 FK를 클래스에서 지정하고 fetch=FetchType~~~어쩌고저쩌고

 

이렇게 쓴적이있다. ex ) @ManyToOne(fetch=FetchType.LAZY)

 

이 fetch는 LAZY, 즉, 지연로딩에 관한 것이었고

 

지금 사용하는 이 fetch는 쿼리문 작성할때 사용한다.

 

아래처럼 join 쿼리 작성시 끼워넣는다.

 

String query = "select m from Member m join fetch m.team";

 

일단 fetch를 사용하지 않고 아래를 실행해보자.

 

Team team = new Team();
team.setName("teamA");
em.persist(team);

Team team1 = new Team();
team1.setName("teamB");
em.persist(team1);

Member member = new Member();
member.setUsername("userA");
member.setAge(10);
member.setType(MemberType.ADMIN);

Member member1 = new Member();
member1.setUsername("userB");
member1.setAge(70);
member1.setType(MemberType.USER);

Member member2 = new Member();
member2.setUsername("userC");
member2.setAge(90);
member2.setType(MemberType.USER);

member.setTeam(team);
member1.setTeam(team1);
member2.setTeam(team1);

em.persist(member);
em.persist(member1);
em.persist(member2);


em.flush();
em.clear();

String query = "select m from Member m";
List<Member> resultList = em.createQuery(query, Member.class).getResultList();

for (Member member : resultList) {
System.out.println("member = " + member.getUsername()+","+member.getTeam().getName());
}

System.out.println(" ======================================================= ");
tx.commit(); //이시점에 DB 쿼리가 날라감

 

 

 

실행을 하면 em.clear(); 이후에 쿼리는 select m from Member m 이때 member만 일단 select 쿼리가 나가게 된다.

 

왜냐하면 Member 에서 Team변수에 지연로딩을 걸어놨기 때문에 조인이 안된 상태로 Member만 select 때린다.

 

이때 proxy 객체를 얻어온다. (그냥 객체가 아니다, 왜냐면 지연로딩이기 때문에 - 지연로딩= 프록시객체 얻어옴)

 

그리고 아래에 member3.getTeam().getName() 을 딱 호출하면 team과 연관된 데이터를 건드렸기 때문에 team select

 

문이 호출되면서 프록시 객체가 없어지고 그냥 일반 객체로 변하게 된다.

 

그러면 teamA에 관한 첫번째 member가 출력이 된다. 만약 teamA가 2명이면 2명의 member가 출력되겠지?

 

그러고 또다시 루프를 돌면서 두번째 member에 대해 member.getTeam().getName() 를 할것이고 이때 Team은

 

teamA가 아니라 teamB라서 또다시 DB에서 쿼리를 가져온다.... 뭔가 복잡하다.

 

이때 teamB는 2명이다. 두번째 member일때 select 쿼리를 때리고 세번째 member는 또다시 teamB이기 때문에

 

영속성 컨텍스트에 이미 담긴 놈을 불러오므로 DB에 쿼리를 안때리는것이다..

 

개어렵노.ㅡㅡ

 

지금 적는것 조차 뭔가 복잡하고 알아듣기 어렵지만... 내 자신은 이해를 완벽히 해서 다행일뿐이다.

 

 

========================================================================

 

결론은 팀이 다른 100명의 멤버를 만약 루프를 돌리면 team select 쿼리를 100번 때리게 된다는 것이다.

 

겁나 비효율적이지 않나?

 

그래서 사용하는게 fetch이다.

 

사용법은 간단하다. 

 

String query = "select m from Member m join fetch m.team";

 

이렇게 하면된다.

 

이렇게 사용하면 join 할때 아예 전체 데이터를 DB에서 가져온다.

 

그래서 실행하면.

 

이렇게 getResultList 할때 딱 한번만 join해서 가져오고 그뒤에 루프돌때는 DB에 안간다.

 

그래서 루프 돌때 team객체는 프록시 객체가 아니다. 그냥 실제 엔티티다.

 

 

이게바로 fetch 조인이다....실무에서 겁나 쓴다. 기억하자

'Developer' 카테고리의 다른 글

[JAP]fetch 조인 - 특징과 한계  (0) 2020.09.22
[JPA]JPQL - distinct 중복제거  (0) 2020.09.22
[JPA]JPQL 기본 함수  (0) 2020.09.21
[JPA]COALESCE와 NULLIF  (0) 2020.09.21
[JPA]조건식 - CASE  (0) 2020.09.21
  Comments,     Trackbacks