반응형
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 |