JPQL 서브쿼리

wannabeking·2022년 8월 9일
0

회고

목록 보기
5/18

진행 중인 프로젝트에는 폴더마다 여러개의 태그가 존재한다.
또한 태그에는 대분류, 소분류가 존재하여 RootTagTag로 나뉜다.

필자는 태그로 폴더 검색 기능을 구현하던 중, 다음과 같은 문제를 겪었다.

	@Query(value = "SELECT DISTINCT f FROM Folder f JOIN FETCH f.user " +
    	"JOIN FETCH f.folderTags ft JOIN ft.tag t " +
    	"ON t.name = :tag WHERE f.isPrivate = false",
    	countQuery = "SELECT count(f) FROM Folder f")
    Page<Folder> findByTag(TagCategory tag, Pageable pageable);

위와 같은 쿼리를 사용하면 검색을 위해 사용된 태그만 가지고 있는 객체들이 반환된다.

당연하게도 on 절에 t.name = :tag를 사용했기 때문이다.

원하는 것은 원래 가지고 있는 태그들을 온전히 가진 폴더 객체들을 가져오는 것이었고, 따라서 서브쿼리를 사용하게 되었다.

	@Query(value = "SELECT DISTINCT f FROM Folder f " +
    	"JOIN FETCH f.user JOIN FETCH f.folderTags ft " +
        "WHERE f.isPrivate = false AND f.id IN " +
        "(SELECT subf.id FROM Folder subf JOIN subf.folderTags subft " +
        "JOIN subft.tag subt ON subt.name = :tag)",
        countQuery = "SELECT count(f) FROM Folder f")
    Page<Folder> findByTag(TagCategory tag, Pageable pageable);

서브쿼리를 사용하여 해당 태그를 가지고 있는 폴더의 id를 다중열로 select한 뒤, 해당 id를 가지고 있는 폴더들을 select하는 로직으로 수정하였다.

이제 FolderTag를 fetch join하면 폴더가 가지고있는 태그들이 잘 받아와진다.

하지만, 서브쿼리를 사용한 방법은 성능이 좋지 않다.

따라서 비정규화를 이용한 방법 등을 고민해봐야할 것 같다.



profile
내일은 개발왕 😎

0개의 댓글