JPA

일대다 페이징처리

lby132 2023. 3. 27. 23:45

JPA에서 일대다관계와 join fetch를 하게 되면 콘솔창에 데이터를 메모리에 올리겠다는 WARN이 뜬다. 

일대다이면 데이터가 뻥튀기가 되기 때문에 페이징처리가 이상하게 될수 밖에 없어서 이 선택을 한것같다고 한다.

그래서 

jpa:
  hibernate:
    ddl-auto: create
  properties:
    hibernate:
      format_sql: true
      default_batch_fetch_size: 100

default_batch_fetch_size: 100 를 잡아주는데 이러면 일대 "다"로 되어있는 애들을 다 끌고 와서 한번에 조회하게 된다.

    select
        orderitem0_.order_id as col_0_0_,
        item1_.name as col_1_0_,
        orderitem0_.order_price as col_2_0_,
        orderitem0_.count as col_3_0_ 
    from
        order_item orderitem0_ 
    inner join
        item item1_ 
            on orderitem0_.item_id=item1_.item_id 
    where
        orderitem0_.order_id in (
            ? , ?
        )

이런식으로 in 절에 데이터를 한번에 담아서. (원래는 데이터갯수당 하나씩 쿼리가 나감(중복조회 없다고 가정했을때))

그러니까 데이터가 1000개면 100개씩 열번 루프를 돌면서 in 쿼리로 데이터들을 다 불러옴 그러면서 일대다 관계도 페이징처리가 가능하게 된다. 물론 다대일 관계나 일대일 같은 관계는 중복데이터 발생이 없기 때문에 얼마든지 페이지가 가능하다.

어쨋든 이 방법을 써서 페이징 처리를 해주면 되는데 100개를 한번에 가져왔을때 DB성능 문제가 생길수 있으니 50개로 지정할수 있지만 어차피 1000개를 가져올만큼의 루프를 돌려야 하기 때문에 엄청난 차이는 없을것 같지만 그때 상황에 맞게 잘 선택해서 사용해야할것 같다.

그리고 만약 데이터가 엄청 많은걸 불러올땐 join fetch를 쓰면 한번에 다 불러오기 때문에 성능이슈가 있을 수 있으니 그럴 때도 default_batch_fetch_size를 써줘도 좋다고 한다. 물론 default_batch_fetch_size 를 사용하면 쿼리가 여러번 나가긴 하지만.

 

'JPA' 카테고리의 다른 글

flush mode옵션  (0) 2023.05.14
entity  (0) 2023.03.29
필드와 컬럼매핑 + 기본키 매핑  (0) 2022.12.04
Merge와 변경감지  (0) 2022.11.26
Join Fetch  (0) 2022.10.21