• 먼저 생각해 볼 수 있는 방법은 @EntityGraph로 한 번에 다 가져올 수 있습니다.
  • join fetch을 사용하여 한 번에 쿼리 할 수 있습니다.
  • hibernate의 default batch를 사용하는 방법이 있습니다.

3. Hibernate의 default batch를 사용하는 방법

spring boot를 사용하여 application.yml에 다음 항목을 설정하면 됩니다.

spring:

  jpa:

    properties:

      hibernate.default_batch_fetch_size: 1000

===== LAZY
Hibernate: 
    select
        post0_.id as id1_1_,
        post0_.title as title2_1_ 
    from
        post post0_
2020-06-15 15:32:53.655 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_1_] : [BIGINT]) - [1]
2020-06-15 15:32:53.659 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([title2_1_] : [VARCHAR]) - [첫 포스트]
2020-06-15 15:32:53.660 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_1_] : [BIGINT]) - [4]
2020-06-15 15:32:53.660 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([title2_1_] : [VARCHAR]) - [내가 2등~]
2020-06-15 15:32:53.667 TRACE 9690 --- [    Test worker] org.hibernate.type.CollectionType        : Created collection wrapper: [com.icatapark.jpa.post.entity.Post.comments#1]
2020-06-15 15:32:53.667 TRACE 9690 --- [    Test worker] org.hibernate.type.CollectionType        : Created collection wrapper: [com.icatapark.jpa.post.entity.Post.comments#4]
Hibernate: 
    select
        comments0_.post_id as post_id3_0_1_,
        comments0_.id as id1_0_1_,
        comments0_.id as id1_0_0_,
        comments0_.comment as comment2_0_0_,
        comments0_.post_id as post_id3_0_0_ 
    from
        comment comments0_ 
    where
        comments0_.post_id in (
            ?, ?
        )
2020-06-15 15:32:53.672 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [4]
2020-06-15 15:32:53.673 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [BIGINT] - [1]
2020-06-15 15:32:53.676 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_0_] : [BIGINT]) - [2]
2020-06-15 15:32:53.677 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([comment2_0_0_] : [VARCHAR]) - [첫 댓글~! ]
2020-06-15 15:32:53.677 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_0_] : [BIGINT]) - [1]
2020-06-15 15:32:53.678 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_1_] : [BIGINT]) - [1]
2020-06-15 15:32:53.678 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_1_] : [BIGINT]) - [2]
2020-06-15 15:32:53.683 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_0_] : [BIGINT]) - [3]
2020-06-15 15:32:53.683 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([comment2_0_0_] : [VARCHAR]) - [두번째야~]
2020-06-15 15:32:53.684 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_0_] : [BIGINT]) - [1]
2020-06-15 15:32:53.684 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_1_] : [BIGINT]) - [1]
2020-06-15 15:32:53.685 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_1_] : [BIGINT]) - [3]
2020-06-15 15:32:53.685 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_0_] : [BIGINT]) - [5]
2020-06-15 15:32:53.685 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([comment2_0_0_] : [VARCHAR]) - [좋아요~]
2020-06-15 15:32:53.686 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_0_] : [BIGINT]) - [4]
2020-06-15 15:32:53.686 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_1_] : [BIGINT]) - [4]
2020-06-15 15:32:53.686 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_1_] : [BIGINT]) - [5]
2020-06-15 15:32:53.687 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_0_] : [BIGINT]) - [6]
2020-06-15 15:32:53.688 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([comment2_0_0_] : [VARCHAR]) - [감사합니다.]
2020-06-15 15:32:53.688 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_0_] : [BIGINT]) - [4]
2020-06-15 15:32:53.689 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_1_] : [BIGINT]) - [4]
2020-06-15 15:32:53.694 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_1_] : [BIGINT]) - [6]
2020-06-15 15:32:53.695 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_0_] : [BIGINT]) - [7]
2020-06-15 15:32:53.696 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([comment2_0_0_] : [VARCHAR]) - [다음글 기대할께요.]
2020-06-15 15:32:53.696 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_0_] : [BIGINT]) - [4]
2020-06-15 15:32:53.696 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([post_id3_0_1_] : [BIGINT]) - [4]
2020-06-15 15:32:53.697 TRACE 9690 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_1_] : [BIGINT]) - [7]
LAZY : [[Comment(id=2, comment=첫 댓글~! ), Comment(id=3, comment=두번째야~)], [Comment(id=5, comment=좋아요~), Comment(id=6, comment=감사합니다.), Comment(id=7, comment=다음글 기대할께요.)]]

프록시를 통해서 연관된 entity의 실제 값을 가져오는 DB 쿼리를 in 절로 수정되어서 한 번에 쿼리가 됩니다.

그리고 @BatchSize 어노테이션을 class나 method, member variable에 각각 적용도 가능합니다. (실제 테스트 결과 @OneToMany에 적용했을 때만 동작했습니다. Entity class에 @BatchSize를 적용하는 방법은 좀 더 확인이 필요한 것 같습니다.)

@Entity
@BatchSize(size=100)
class Product {
    @OneToMany
    @BatchSize(size = 10) /
    Set<Product> getProducts() { ... };
}

 

'Programming > JPA' 카테고리의 다른 글

N + 1 문제 해결 2  (0) 2020.06.11
N + 1 문제 해결 1  (0) 2020.06.11
N + 1 문제 원인  (0) 2020.06.05
왜 JPA를 써야할까?  (0) 2020.06.05
JPA 기본 Annotation 정리  (7) 2019.07.04

+ Recent posts