Search
Duplicate

기본 문법

JPQL vs Querydsl

Before:: 원천 데이터 셋업

Code

JPQL vs Querydsl

Code

JPAQueryFactory 를 필드로 뺄 수도 있다.

Code
참고: JPAQueryFactory를 필드로 제공하면 동시성 문제(Multi Threading)은 어떻게 될까? → 스프링 프레임워크는 여러 쓰레드에서 동시에 같은 EntityManager에 접근해도, 트랜잭션 마다 별도의 영속성 컨텍스트를 제공하기 때문에, 동시성 문제는 일어나지 않는다.

기본 Q-Type 활용

위의 Querydsl 예제에서는 Q클래스의 인스턴스를 사용할 때 new QMember("m") 와 같이 new 를 통해 별칭을 직접 지정해줬지만, Querydsl 에서 제공하는 기본 인스턴스를 사용하는게 더 간편하다.
QMember qMember = new QMember("M"); // 별칭 직접 지정 QMember qMember = QMember.member; //기본 인스턴스 사용
Java
복사
Q클래스를 static-import 해주면 member 도 바로 사용할 수 있다.
import static study.querydsl.entity.QMember.*; @Test public void startQuerydsl3(){ Member findMember = queryFactory.selectFrom(member).where(member.id.eq(1L).fetchOne(); assertThat(findMember.getId)).isEqualTo(1L); }
Java
복사

검색 조건 쿼리

기본 검색 쿼리

Code

AND 조건을 메서드 체인 말고 파라미터로 처리할 수도 있습니다.

Code

JPQL이 제공하는 모든 검색 조건을 제공합니다.

member.username.eq("a") : username = 'a'
member.username.ne("a") : username ≠ 'a'
member.username.eq("a").not() : username ≠ 'a'
member.username.isNotNull() : username is not null
member.age.in(10,20) : age in (10,20)
member.age.notIn(10,20) : age not in(10,20)
member.age.between(10,30) : age between 10, 30
member.age.goe(30) : age ≥ 30
member.age.gt(30) : age > 30
member.age.loe(30) : age ≤ 30
member.age.lt(30) : age < 30
member.username.like("member%") : username like 'member%'
member.username.contains("member') : username like '%member%'
member.username.startsWith("member") : like 'member%'
.... 등등

결과 조회

→ queryFactory 를 통해 생성한 쿼리들(queryFactory.select(member).from(member).where(member.id.eq(1L))...) )의 결과를 반환하는 함수들에 대해 소개한다.

fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환
fetchOne() : 단 건 조회
결과가 없으면: null
결과가 둘 이상이면: com.querydsl.core.NonUniqueResultException
fetchFirst() : limit(1).fetchOne() 과 같다.
fetchResults() : 페이징 정보 포함, total count 쿼리 추가 실행
fetchCount() :count 쿼리로 변경해서 count 수 조회

테스트 코드 작성 및 검증

Code

정렬

Querydsl 에서는 정렬(Sort)용 메서드 역시 제공된다. → .orderBy(인스턴스명.기준필드.정렬기준.(nullsLast()|nullsFirst()))

정렬 코드 작성 및 검수

Code

페이징

조회 건수 제한

Code

전체 조회 수가 필요한 경우

Code

집합

JPQL이 제공하는 모든 집합 함수를 Querydsl 에서 제공한다.

집함 함수 코드

Code

Group By 사용 → 팀의 이름과 각 팀의 평균 연령을 구해라.

Code

조인 - 기본 조인

→ Querydsl 에서는 JOIN 함수도 역시 제공된다.

join() , innerJoin() : 내부 조인(inner join)
leftJoin() : left 외부 조인(left outer join)
rightJoin() : right 외부 조인(right outer join)
JPQL의 on 과 성능 최적화를 위한 fetch 조인 제공

그렇다면 연관관계가 없는 엔티티간의 조인은 어떻게 하는가? → 세타 조인

Code

조인 - on절

ON 절을 활용한 조인(JPA 2.1부터 지원)

조인 대상 필터링
연관관계 없는 엔티티 외부 조인

1. 조인 대상 필터링

회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회
Code

2. 연관관계 없는 엔티티 외부 조인

회원의 이름과 팀의 이름이 같은 대상 외부 조인
Code

조인 - 페치 조인

페치 조인은 SQL 자체적으로 제공하는 기능은 아니고 JPA에서 SQL조인을 활용해서 연관된 엔티티를 SQL 한 번에 조회해 가져오는 기능입니다. 성능 최적화를 위해 엔티티 연관관계에서 모든 로딩전략을 지연로딩(fetch = fetchType.LAZA)으로 설정하는데, 페치조인을 사용하면, getter 호출시마다 쿼리를 수행하는 것을 막을 수 있습니다.

Before:: 페치 조인 미적용

→ 지연로딩으로 Member, Team SQL 쿼리 각각 실행
Code

After::페치 조인 적용

→ 즉시로딩으로 Member, Team SQL 쿼리 조인으로 한 번에 조회
Code

서브 쿼리

com.querydsl.jpa.JPAExpressions 를 사용하여 서브쿼리 사용이 가능하다.

서브쿼리 eq 사용

Code

서브쿼리 goe 사용

Code

서브쿼리 여러 건 처리 in절 사용

Code

서브쿼리 select 절에서 사용sele

Code
from절의 서브쿼리 한계 → JPA JPQL 서브쿼리의 한계점으로 from절의 서브쿼리(인라인 뷰)는 지원하지 않습니다. JPQL 쿼리 빌더인 Querydsl 역시 같은 이유로 지원하지 않습니다. 하이버네이트 구현체를 사용하면 select절의 서브쿼리는 지원합니다. Querydsl도 하이버네이트 구현체를 사용하면 select 절 서브쿼리를 지원합니다.
from절의 서브쿼리 한계돌파 방안
1.
서브쿼리 → JOIN 으로 변경한다. (가능한 상황도 있고, 불가능한 상황도 있다.)
2.
애플리케이션에서 쿼리를 2번 분리해서 실행한다.
3.
nativeSQL 을 사용한다.

Case 문

Querydsl 에서 select, 조건절(where)에서 사용 가능합니다.

단순한 조건

Code

복잡한 조건

Code

상수, 문자 더하기

상수가 필요하다면 Expressions.constant(xxx) 사용

Code
참고: 위와 같이 최적화가 가능하면 SQL에 constant 값을 넘기지 않는다. 상수를 더하는 것 처럼 최적화가 어려우면 SQL에 constant값을 넘긴다

문자 더하기 concat

Code
참고: member.age.stringValue() : 문자가 아닌 다른타입(ex: int, float..)들을 문자로 변환해준다. 이 방법은 ENUM을 처리할 때도 자주 사용한다.