XtoOne (ManyToOne, OneToOne)
관계에 있어서 fetch join
을 사용하면 n + 1 문제가 해결 되는 것을 경험했다. 그런데 fetch join
의 치명적인 단점은 페이징을 못한다는 것이다. 정확하게 말하면 fetch join
을 사용하는 동시에 페이징을 시도하면 하이버네이트는 db에 있는 모든 데이터를 메모리에 가져온 후에 메모리 내에서 페이징을 해버린다. 만약에 db에 데이터가 많은 애플리케이션이라면 out of memoery로 서버가 뻗을 수 있다. 이런 문제를 해결해주는 것이 바로 @BatchSize
, hibernate.default_batch_fetch_size
이다.
# resources/application.yml 에 있는 파일
spring:
jpa:
...
properties:
hibernate:
default_batch_fetch_size: 1000 #최적화 옵션
default_batch_fetch_size
를 사용하면 설정한 수만큼 컬렉션이나 프록시 객체를 한번에 가져온다.In 쿼리
를 사용하므로 DB 데이터 전송량이 감소한다. public List<Order> findAllWithMemberDelivery(int offset, int limit) {
return em.createQuery(
"select o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d", Order.class)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
}
default_batch_fetch_size
를 설정해주면 fetch join과 함께 페이징 사용 시 나오는 경고 문구가 사라지게 된다.