반응형
QueryDSL 기본문법
기본적인 조회
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
QueryDSL
을 이용한 기본적인 where절을 이용한 조회이다.- QMember와 같이 QType 클래스를 static import하여 사용하면 간결한 코드를 구성할 수 있다.
- 별칭을 다르게 두어야 한다면 새로 선언하자.
검색조건
Member findMember = queryFactory
.selectFrom(member)
.where(member.username.eq("member1").and(member.age.between(10, 30)))
.fetchOne();
- where절에는 and나 or을 사용할 수 있다.
- and 연산의 경우
.where(member.username.eq("member1"), member.age.between(10, 30))
와 같이,
를 이용해 간단하게 사용할 수도 있다.- 또한 해당 검색조건이
null
일 경우 무시한다. 따라서 동적 쿼리를 깔끔하게 구성할 수 있다.
- 또한 해당 검색조건이
- where절 안에는 여러 검색 조건이 사용 가능하다.
eq()
: A = ?ne()
: A != ?eq().not()
: A != ?isNotNull()
: A is not nullin()
: A in (?)notIn()
: A not in (?)between()
: A between ?, ?goe()
: A >= ?gt()
: A > ?loe()
: A <= ?lt()
: A < ?like()
: A like ?contains()
: A like "%?%"startWith()
: A like "?%?
결과조회
fetch()
: 리스트를 조회한다, 값이 없을 때에는 빈 리스트가 반환된다.fetchOne()
: 단 건 조회- 결과가 없을 때에는
null
을 리턴한다. - 결과가 둘 이상일 때에는
NonUniqueResultException
이 발생한다.
- 결과가 없을 때에는
fetchFirst()
:limit(1).fetchOne()
과 동일하다.fetchResults()
: 페이징 정보를 포함하여 total count쿼리를 추가로 실행시킨다.- 이후
getTotal()
과getResult()
메서드로 정보를 조회할 수 있다.
- 이후
fetchCount()
: count쿼리로 변형해 count수를 조회한다.
페이징
QueryResults<Member> queryResults = queryFactory
.selectFrom(member)
.orderBy(member.username.desc())
.offset(1)
.limit(2)
.fetchResults();
offset()
: 시작점을 설정한다.limit()
: 최대 조회 수를 설정한다.listResults()
:QueryResults
타입으로 리턴받는다.QueryResults.getTotal()
: 전체 수 조회QueryResults.getLimit()
: limit 조회QueryResults.getOffset()
: offset 조회QueryResults.getResults()
: 결과값 조회
정렬
- 정렬은
orderBy
를 사용한다. asc()
: 오름차순 정렬desc()
: 내읾차순 정렬nullsLast()
,nullsFirst
: null값의 위치를 설정한다.asc().nullsLast()
와 같은 형태로 사용한다.
집합
List<Tuple> result = queryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
.fetch();
- JPQL이 제공하는 모든 집합 함수를 제공한다.
- 집합 함수를 사용하면 tuple로 결과값이 리턴된다.
- 함수
COUNT()
: 개수SUM()
: 합AVG()
: 평균MAX()
: 최대MIN()
: 최소
groupBy()
: 필드명을 이용해 그룹화한다.having()
: having절 사용
조인
List<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("teamA"))
.fetch();
- join은
.join(조인대상, 별칭쿼리타입)
의 형태로 사용한다.innerJoin()
: sql의 innerJoinleftJoin()
: sql의 leftJoinrightJoin()
: sql의 rightJoinfullJoin()
: sql의 fullJoin
on()
: join의 on절을 사용한다.- on절을 사용해 조인 대상을 필터링하는 것은
innerJoin
사용시where
절로 필터링하는 것과 동일하다. - 내부조인이면 where을 사용하고, 외부조인인 경우에 사용한다.
- on절을 사용해 조인 대상을 필터링하는 것은
fetch()
: join에 페치조인을 적용한다.innerJoin(~~).fetch()
의 형태로 사용한다.
서브쿼리
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions
.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
- 서브쿼리는
JPAExpressions
를 이용한다. - 주로 새로운
QType
을 정의하여 사용한다. - static import를 이요하면 깔끔한 코드를 작성할 수 있다.
FROM절
의 서브쿼리- JPA JPQL에서는 FROM절의 서브쿼리를 허용하지 않는다.
- 따라서 서브쿼리를 join변경, 애플리케이션 쿼리 분리, nativeSQL을 사용하는 방안으로 해결해야 한다.
CASE문
List<String> result = queryFactory
.select(member.age
.when(10).then("열살")
.when(20).then("스무살")
.otherwise("기타")
)
.from(member)
.fetch();
when()
: sql의 whenthen()
: when에 해당할 때otherwise()
: 나머지 상황
조건을 변수로 선언하기
NumberExpression<Integer> rankPath = new CaseBuilder()
.when(member.age.between(0, 20)).then(2)
.when(member.age.between(21, 30)).then(1)
.otherwise(3);
- 위와 같이 조건을 변수로 선언하여 실 코드에서 사용할 수 있다.
상수, 문자 더하기
List<Tuple> result = queryFactory
.select(member.username, Expressions.constant("A"))
.from(member)
.fetch();
List<Tuple> result = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue()), member.age)
.from(member)
.where(member.username.eq("member1"))
.fetch();
Expressions.constant()
: 상수를 더할 때 사용한다.concat()
: 문자를 더할 떄 사용한다.
마침
대체적으로 SQL, JPQL의 문법을 따라가는 형태를 취한다.
그리고 복잡한 sql을 자바 코드로 사용한다는 것, 컴파일 단계에서 오류를 잡아낼 수 있다는 것은 굉장히 매력적인 것 같다.
반응형
'Java & Kotlin > Spring Data' 카테고리의 다른 글
[QueryDSL] 벌크연산과 SQL Funtion (0) | 2022.05.15 |
---|---|
[QueryDSL] 동적쿼리 (0) | 2022.05.14 |
[QueryDSL] 프로젝션 (0) | 2022.05.14 |
[QueryDSL] QueryDSL 시작하기 (0) | 2022.05.10 |
[JPA] UniqueConstraint와 Embedded field (0) | 2022.05.07 |
[JPA]영속성 전이 CASCADE (0) | 2022.04.21 |