기존에 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가 사라진것을 확인할 수 있다!
행복하다..!!