03.17 QueryDSL 기본문법
2023. 3. 17. 21:31ㆍ개발일지
기본적인 조회
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 null
- in(): 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의 innerJoin
- leftJoin(): sql의 leftJoin
- rightJoin(): sql의 rightJoin
- fullJoin(): sql의 fullJoin
- on(): join의 on절을 사용한다.
- on절을 사용해 조인 대상을 필터링하는 것은 innerJoin사용시 where절로 필터링하는 것과 동일하다.
- 내부조인이면 where을 사용하고, 외부조인인 경우에 사용한다.
- 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의 when
- then(): 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을 자바 코드로 사용한다는 것, 컴파일 단계에서 오류를 잡아낼 수 있다는 것은 굉장히 매력적인 것 같다.
'개발일지' 카테고리의 다른 글
03.25 TIL (0) | 2023.03.25 |
---|---|
03.24 이메일 인증(feat. 네이버,구글) (0) | 2023.03.24 |
Nginx와 Let's Encrypt로 HTTPS 웹 서비스 배포하기 (feat. Certbot) (0) | 2023.03.16 |
03.08 multipart 이미지 파일 리사이징 해서 파일 만들기 (0) | 2023.03.08 |
03.07 JPA Pagination을 이용한 무한 스크롤 구현기 (0) | 2023.03.06 |