이 방법도 역시 간단하다. 지난번까지 사용했었던 배치 패칭 설정은 지우고 다음과 같이 설정한다.

@OneToMany(mappedBy="owner", fetch=FetchType.EAGER)
@BatchSize(size=30)
private Set items;

이렇게 설정하면 Member 클래스를 Criteria나 Session.get(), load()로 읽어올 때 C도 같이 로딩해온다. 그래서 eager다. Lazy Collection Fetching과 정반대다.

주의 할 것이 있는데, 이 설정은 HQL에선 먹히지 않는다. 확인해보자.

[java]
@Test
public void eagerFetchingByCriteria(){
int mostItemCount = 0;
Member mostItemOwner = null;

List<Member> memberList = getSession().createCriteria(Member.class).list();
for (Member thisMember : memberList) {
Set<Item> memberItems = thisMember.getItems();
if(mostItemCount < memberItems.size()) {
mostItemCount = memberItems.size();
mostItemOwner = thisMember;
}
}

System.out.println(mostItemCount);
System.out.println(mostItemOwner);
}
[/java]

이렇게 Criteria를 사용하면 다음과 같이 Member를 가져올때 left outer join으로 Member가 가지고 있는 모든 Item을 다 가져온다.

[java]
@Test
public void eagerFetchingByHQL(){
int mostItemCount = 0;
Member mostItemOwner = null;

List<Member> memberList = getSession().createQuery("from Member").list();
for (Member thisMember : memberList) {
Set<Item> memberItems = thisMember.getItems();
if(mostItemCount < memberItems.size()) {
mostItemCount = memberItems.size();
mostItemOwner = thisMember;
}
}

System.out.println(mostItemCount);
System.out.println(mostItemOwner);
}
[/java]

하지만 이렇게 HQL을 사용하면 N+1 Select 문제가 여전히 발생한다.


이런 경우를 대비해 @BatchSize를 다시 붙여 놓는게 좋을 거 같기는 하다.

[java]
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
@BatchSize(size=30)
private Set<Item> items;
[/java]
이렇게 배치 패칭을 설정해 두면 그래도 완벽하진 않지만 HQL을 사용하는 경우를 대비해서, 어느정도 성능을 개선할 수는 있다.

자 이렇게 Eager 패칭을 사용하는 방법을 알아봤지만, 이 방법에는 큰 문제가 하나 있다. 매핑 정보에서 패칭 전략을 Eager로 설정했기 때문에 앞으로 Session.get(), load()로 어떤 Member 객체 하나를 읽어간다고 하도 해당 Member의 List까지 매번 같이 가져가게 된다. 매번 필요한 정보라면 그렇게 하는게 맞겠지만 필요없는 경우라면 오히려 불필요한 메모리 소비와 성능만 소비하게 되는 꼴이다.

하지만 분명히 이 방법이 유용한 경우도 있겠다.