JPA Lazy Loding N+1 문제를 방지하기 위해 사용된다.
return jpaQueryFactory.selectFrom(instagram)
.innerJoin(instagram.place, place)
.fetchJoin()
.fetch();
Hibernate:
select
instagram0_.instagram_id as instagra1_4_0_,
place1_.place_id as place_id1_8_1_,
instagram0_.created_date as created_2_4_0_,
instagram0_.modified_date as modified3_4_0_,
instagram0_.hashtag_count as hashtag_4_4_0_,
instagram0_.hashtag_name as hashtag_5_4_0_,
instagram0_.place_id as place_id6_4_0_,
place1_.created_date as created_2_8_1_,
place1_.modified_date as modified3_8_1_,
place1_.category as category4_8_1_,
place1_.kakao_id as kakao_id5_8_1_,
place1_.latitude as latitude6_8_1_,
place1_.longitude as longitud7_8_1_,
place1_.road_address_name as road_add8_8_1_,
place1_.place_name as place_na9_8_1_,
place1_.place_url as place_u10_8_1_
from
instagram instagram0_
inner join
place place1_
on instagram0_.place_id=place1_.place_id
내가 헷갈렸던 부분은
return jpaQueryFactory.selectFrom(instagram)
.innerJoin(instagram.place, place)
.fetchJoin() // 여기서의 fetch 1
.fetch(); // 또 여기서의 fetch 2
요렇게 fetch가 2번 나와서 헷갈렸다.
두번째 fetch는 결과 반환의 용도이다.
결과반환
갓졸두님 블로그를 보면서 한번도 생각하지 못한 것을 알게 되었다.
OneToMany 관계에서 findAllBatchJoin할 때 의도치 않게 동일한 One이 여러 개 반환될 수 있다는 것이다.
class One {
...
@OneToMany(fetchType=Lazy)
@JoinColumn(name = "many_id")
List<Many> manyList;
}
One 안에 3개의 Many 있다.
이때, fetchJoin으로 데이터를 가져오면
select
one, many
from
one
inner join
many
on
one.id=many.id
요런 식의 Query가 생긴다.
그러면 3개의 row가 return되면서 One 3개가 생긴다!
private void setUp() {
One one = new One();
List<Many> manyList = manyRepository.saveAll(Arrays.asList(new Many(), new Many(), new Many()));
one.manyList = manies;
oneRepository.save(one);
}
@Test
void test() {
setUp();
List<One> ones = testRepository.findAllFetch();
assertThat(ones).hasSize(3);
assertThat(ones.get(0)).isSameAs(allFetch.get(1));
assertThat(ones.get(0)).isSameAs(allFetch.get(2));
}
이래서 OneToMany를 지양하나보다!