Querydsl을 사용하여 Dto 리스트를 직접 반환하는 방식은 데이터베이스로부터 데이터를 조회할 때 필요한 정보를 한 번의 쿼리로 완전히 가져오기 때문에, stream().map() 과정을 거치지 않아도 된다. 즉, Querydsl 쿼리에서 Projections.fields() (또는 다른 Projections 방법)를 사용함으로써 필요한 데이터를 바로 DTO 형태로 매핑하고, 추가적인 변환 과정 없이 바로 결과를 반환할 수 있다.
1. 성능 최적화: 한 번의 쿼리로 필요한 모든 데이터를 가져올 수 있으므로, 네트워크 라운드 트립을 줄이고, 전체적인 성능을 향상시킬 수 있습니다. stream().map() 과정에서 발생할 수 있는 추가적인 쿼리 실행(예: postService.getPostId(bookmark.getPost().getId()) 호출)이 필요 없습니다.
2. 코드 간소화: 데이터를 가져온 후 Java 스트림 API를 사용하여 객체를 변환하는 추가적인 작업이 없으므로, 코드가 더 간결하고 명확해집니다. 이는 유지보수성을 높이는 데 도움이 됩니다.
3. 타입 안전성: Querydsl을 사용하면, 컴파일 시점에 쿼리의 타입 안전성을 검증할 수 있습니다. 즉, 개발 중에 쿼리 관련 실수를 더 쉽게 발견하고 수정할 수 있습니다.
QueryDSL의 목적은 JPQL 생성이다. 개발자는 QueryDSL이 JPQL을 생성할 수 있도록 필요한 데이터를 세팅하여 전달해야 한다. 일단 Entity 정보가 필요하다. 그러나 Entity는 JPA프레임워크에서 지원하는 모듈이다. QueryDSL은 쿼리생성에 특화된 프레임워크로, JPA 프레임워크와 분리되어 있다. 그러므로 다른 프레임워크의 모듈을 그대로 사용하면 JPA프레임워크에 종속되어버린다. 이런 현상을 막고자, QueryDSL은 Entity 정보를 담은 Q타입클래스 를 사용한다.
QMember qMember = new QMember("m"); //별칭 직접 지정
QMember qMember = QMember.member; //기본 인스턴스 사용
import static study.querydsl.entity.QMember.*;
@Test
public void startQuerydsl() {
//member1을 찾아라.
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
fetch()
: 리스트 조회, 데이터 없으면 빈 리스트 반환 `fetchOne()
: 단 건 조회null
com.querydsl.core.NonUniqueResultException
fetchFirst()
: limit(1).fetchOne()
fetchResults()
: 페이징 정보 포함, total count 쿼리 추가 실행fetchCount()
: count 쿼리로 변경해서 count 수 조회//List
List<Member> fetch = queryFactory
.selectFrom(member)
.fetch();
//단 건
Member findMember1 = queryFactory
.selectFrom(member)
.fetchOne();
//처음 한 건 조회
Member findMember2 = queryFactory
.selectFrom(member)
.fetchFirst();
@Test
public void paging1() {
List<Member> result = queryFactory
.selectFrom(member)
.orderBy(member.username.desc()) // username 기준 내림차순 정렬
.offset(0) // 0부터 시작(zero index)
.limit(5) // 최대 5건 조회
.fetch();
assertThat(result.size()).isEqualTo(5);
}