QueryDsl을 이용하여 불필요한 join query 삭제

bw1611·2024년 3월 9일

기존에 JPA를 이용하여 전체 조회 쿼리를 실행했을 경우에는 Join Query가 발생하였다!
왜 발생하였을까? 분명 나는 Memo에 authorId가 존재하기 때문에 join query가 발생할 필요가 없었는데...

보여주기 위해서 나의 memo entity는 이렇게 되어있다.

    @Column(name = "title")
    private String title;

    @Column(name = "content")
    private String content;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "author_id")
    private Author author;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "series_id")
    private Series series;

    @Column(name = "affinity")
    @Builder.Default
    private Integer affinity = 0; // 좋아요

    @Column(name = "sequence")
    private Integer sequence;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "parent_memo_id")
    private Memo parentMemo;

    @OneToMany(mappedBy = "parentMemo")
    @Builder.Default
    private Set<Memo> childMemos = new HashSet<>();
@Repository
public interface MemoRepository extends JpaRepository<Memo, Long> {
	Page<Memo> findByAuthorAccountId(UUID accountId, PageRequest pageRequest);
}

이렇게 되어 있어서 author로 조회하게 된다면 절대 join query가 발생하면 안된다고 생각했다.
근데 query는 아래와 같았다..

    select
        m1_0.id,
        m1_0.affinity,
        m1_0.author_id,
        m1_0.content,
        m1_0.created_at,
        m1_0.is_deleted,
        m1_0.deleted_at,
        m1_0.parent_memo_id,
        m1_0.sequence,
        m1_0.series_id,
        m1_0.title,
        m1_0.updated_at      
    from
        memos m1_0      
    left join
        users a1_0              
            on a1_0.id=m1_0.author_id      
    where
        (
            m1_0.is_deleted = 0         
        )          
        and a1_0.id='ea14eb8b-233e-4310-b5d1-08ee4ebf4a01'      
    limit
        10, 10

아래 부분에서 users에 대한 join query가 발생한 것으 보인다.
이 문제를 해결하기 위하여 나는 QueryDsl을 도입하기로 하였다.

구체적인 코드보다는 QueryDsl 부분만 보여주기로 하겠다...

@Slf4j
@Repository
@RequiredArgsConstructor
public class MemoRepositoryImpl implements MemoRepositoryCustom{

    private final JPAQueryFactory queryFactory;

    @Override
    public Page<Memo> findByAuthorId(UUID authorId, Pageable pageable) {
        QMemo memo = QMemo.memo;
        BooleanExpression authorIdEq = memo.author.id.eq(authorId);

        List<Memo> memos = queryFactory
                .selectFrom(memo)
                .where(authorIdEq)
                .orderBy(memo.sequence.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

        Long total = queryFactory
                .select(memo.count())
                .from(memo)
                .fetchOne();

        return new PageImpl<>(memos, pageable, total);
    }
}

QueryDsl을 이용하였다. 우리가 자주 사용하는 sql문이랑 비슷하고 직관적이여서 사용하기도 좋다. 그렇다면 한번 쿼리를 봐보자!

    select
        m1_0.id,
        m1_0.affinity,
        m1_0.author_id,
        m1_0.content,
        m1_0.created_at,
        m1_0.is_deleted,
        m1_0.deleted_at,
        m1_0.parent_memo_id,
        m1_0.sequence,
        m1_0.series_id,
        m1_0.title,
        m1_0.updated_at      
    from
        memos m1_0      
    where
        (
            m1_0.is_deleted = 0         
        )          
        and m1_0.author_id='ea14eb8b-233e-4310-b5d1-08ee4ebf4a01'      
    order by
        m1_0.sequence desc      
    limit
        10, 10

깔끔하게 join query가 사라진것을 확인할 수 있다!
행복하다..!!

profile
Java BackEnd Developer

0개의 댓글