JPA 일대다 조인 데이터 부풀려지기 방지하기
들어가기에 앞서
JPA에서 1:N관계의 두 엔티티를 조인해서 조회하면 데이터가 부풀려지는 현상을 볼 수 있다. 예를 들어 게시글 1개와 이미지 3개를 서로 다른 엔티티에 저장한 뒤 조인해서 조회하면 같은 게시글이 3개가 조회된다. 이것은 1:N관게에서 나타나는 문제이다.
데이터가 부풀려지는 이유
SQL을 사용해보면 1:N상황에서 inner 조인하면 매칭되는 모든 데이터가 나타나게 된다.
게시글 테이블에 "title" 이라는 속성이 있다.
이미지 테이블에 "name"과 게시글 테이블에 대한 외래키가 있다. 이 테이블에는 게시글 테이블에 저장한 2개의 이미지가 저장되어있다. 즉, 게시글 테이블의 외래키가 2개가 있다.
이 상황에서 두 테이블을 조인해서 조회하면
title | name | board_id |
게시글 제목1 | 1번 게시글 이미지1 | 1 |
게시글 제목1 | 1번 게시글 이미지2 | 1 |
이런 결과가 나타날 것이다.
사실 SQL입장에서는 너무 정상적인 데이터이다. 이것을 필요한대로 가공해서 사용하면 되는 것이다.
하지만 JPA입장에서는 조금 다르다. JPA는 ORM으로서 DB를 조회해도 객체지향적으로 데이터를 만들어준다. 만약 이런 조회쿼리를 만들어서 게시글 리스트를 뿌린다면 같은 게시글이 2개가 보여질 것이다.
왜 그럴까??
위의 표에 나타난 데이터를 JPA의 형식으로 변형하면 게시글 엔티티에 2개가 조회되고 조회된 데이터 객체 내부에 각각 이미지가 2개씩 들어가는 형태가 될 것이다. 그렇기 때문에 조회한 게시글 객체를 리스트로 뿌리면 같은 게시글이 2개가 나타나게 되는 것이다. JPA입장에서는 너무 당연한 것이다.
해결방법
해결방법은 엄청 간단하다. distinct를 사용하면 된다.
사실 위의 표와 같이 조회된 쿼리에서 distinct를 사용하면 아무 변화도 일어나지 않는다. 쿼리에서 distinct로 제거할 수 있는 중복은 조회된 행 안에 들어있는 모든 데이터가 다른 행과 같을 때 중복으로 인식되어 없어지기 때문이다.
하지만 위의 표는 이미지가 서로 다른 것으로 조회되기 때문에 중복으로 인식되지 않는다. 그렇지만! JPA에서는 distinct로 사용이 가능하다.
위와 같은 상황을 JPA로 설명하면 아래와 같을 것이다.
게시글 객체1 / 이미지 객체1, 이미지 객체2
게시글 객체1 / 이미지 객체1, 이미지 객체2
이런 상황일 때 JPA에서 distinct를 사용하면 JPA는 같은 주소를 가지는 엔티티를 삭제해준다. 말 그대로 중복을 제거하는 것이다.
그렇게 되면 같은 게시글 객체를 2개 가지고 있을 떄 하나를 제거하기 때문에 결과적으로 하나의 게시글 객체만 불러오게 되는 것이다.
'에러모음' 카테고리의 다른 글
JPA필수코스 N+1문제 해결하기 (0) | 2022.06.25 |
---|---|
스프링부트 gradle build 실패 (0) | 2022.06.15 |
[Error] Mockito를 사용한 단위테스트(form데이터 전송) (0) | 2022.05.17 |
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회 (0) | 2022.05.03 |
[Error] TransientPropertyValueException에러.. (0) | 2022.05.02 |
댓글
이 글 공유하기
다른 글
-
JPA필수코스 N+1문제 해결하기
JPA필수코스 N+1문제 해결하기
2022.06.25 -
스프링부트 gradle build 실패
스프링부트 gradle build 실패
2022.06.15 -
[Error] Mockito를 사용한 단위테스트(form데이터 전송)
[Error] Mockito를 사용한 단위테스트(form데이터 전송)
2022.05.17 -
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회
2022.05.03