QueryDSL
What is Querydsl
Querydsl은 JPA를 편하게 사용할 수 있게 도와주는 Java 프레임워크로 SQL, JPQL을 java코드로 작성 할 수 있도록 해주는 오픈소스이다. 대부분의 SQL언어를 문자열이 아닌 java type으로 작성이 가능하여 IDE와 컴파일 도움을 받기 쉽고 또한 JDBC도 추상화하여 native sql 언어로 직접 데이터베이스에 쿼리를 실행할 수 있다.
QueryDSL quick start
QueryDSL 설정은 여기서 확인하자. https://kha0213.github.io/jpa/querydsl-quick-start/
QueryDSL BASIC
1. Q-Type
모든 Q-Type 클래스는 기본 인스턴스를 제공한다.
기본인스턴스의 이름으로 실제 쿼리시 alias가 나간다.
혹시라도 alias가 겹치는 일이 있으면 안되기 때문에 일반적으로는 이렇게 사용한다.
QMember m = QMember.member;
final Member findMember = queryFactory
.selectFrom(m)
.fetchOne();
💻console
// jpql 이다.
select
member1
from
Member member1
where •••
new 연산자를 사용하여 Q-Type의 별칭을 주는 방법이다. 같은 테이블 조인할 때 사용한다.
QMember m = new QMember("m1");
••• Query 문 추가
💻console
// jpql 이다.
select
m1
from
Member m1
where •••
QueryDSL Grammer
- where
- eq() : = 비교
- ne() : != 비교
- not() : 앞의 내용 부정문
-
isNotNull() : is not null
- in() : in 문법
- notIn() : not in 문법
-
between(a,b) : between a and b
- goe() : 크거나 같다. (>=) // gt or equal
- gt() : 크다
- loe() : 작거나 같다 (<=)
-
lt() : 작다
- like() : like문법 (%넣어줘야 한다.)
- contains() : like문법인데 양쪽에 %넣은 효과.
- startsWith() : like문법인데 뒤에 %넣은 효과.
기본적인 sql문법은 다 있다. 그 외에도 문법 보고 싶으면 ⇾
😀example
member.username.eq("young") // username = 'young'
member.username.ne("young") // username != 'young'
member.username.eq("young").not() // username != 'young'
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,20) // age between 10 and 20
member.age.goe(20) // age >= 20 -- gt or equal
member.age.gt(20) // age > 20
member.age.loe(20) // age <= 20
member.age.lt(20) // age < 20
member.username.like("%mem") // like '%mem'
member.username.contains("mem") // like '%mem%'
member.username.startsWith("mem") // like 'mem%'
where() 안에 들어가는 조건은 , 로 구분하여 여러 개의 and 조건을 할 수 있고 .and()로 체인메서드로 할 수 있다.
member.username.eq("mem").and(member.age.gt(10))) // 하지만 괄호가 많이 생겨서 ,를 추천한다.
member.username.eq("mem"), member.age.gt(10)) // 이걸 추천한다.
member.username.eq("mem"), member.age.gt(10)), null // 중간의 null은 where절에 걸리지 않는다.
member.username.eq("mem").or(member.age.gt(10))) // 물론 or도 있다.
- result
- fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환
- fetchOne() : 단 건 조회 (결과 없으면 null, 둘 이상이면 에러)
- fetchFirst() : 쿼리에 limit 1을 하고 fetchOne()
- fetchResults() : 페이징 정보 포함, (total count 쿼리 추가 실행)
- QueryResults 로 리턴된다. 다음은 QueryResults의 메서드이다.
- getTotal() : count 쿼리로 총 개수를 가져온다.
- getLimit() : limit를 구한다.
- getOffset() : offset을 구한다. (시작이 0)
- getResults() : fetch() 처럼 리스트 리턴한다.
- QueryResults 로 리턴된다. 다음은 QueryResults의 메서드이다.
- fetchCount() : count 쿼리로 변경하여 count 수 조회
😀example
List<Member> fetch = queryFactory
.selectFrom(member)
.fetch();
Member fetchOne = queryFactory
.selectFrom(member)
.where(member.username.eq("member2"))
.fetchOne(); // 단 건 조회 (2건 이상이면 에러!)
Member fetchFirst = queryFactory
.selectFrom(member)
.fetchFirst();
long fetchCount = queryFactory
.selectFrom(member)
.fetchCount();
QueryResults<Member> fetchResults = queryFactory
.selectFrom(member)
.fetchResults();
- sort
- orderBy() 도 마찬가지로 여러 값을 ,를 사용하여 넣을 수 있다.
- .nullsLast()로 null값이 맨 뒤에 오게 할 수도 있고, nullsFirst()로 null값이 맨 처음 오게 할 수도 있다.
😀example
List<Member> members = queryFactory
.selectFrom(member)
.orderBy(member.username.desc(), member.age.asc().nullsLast())
.fetch();
- paging
- offset(n) : n번째부터 시작 (0부터 시작한다.)
- limit(k) : k개의 개수 출력
😀example
// 3번째부터 5개 가져오는 쿼리
final List<Member> members = queryFactory
.selectFrom(member)
.orderBy(member.username.desc().nullsLast())
.offset(2) // 시작이 0부터
.limit(5)
.fetch();
실행된 SQL은 다음과 같다.
💻console
select
member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from
member member0_
order by
case when member0_.username is null then 1 else 0 end,
member0_.username desc limit 2, 5
👍Tip 전체 개수를 구할 때에는 count쿼리를 따로 짤 필요 없이 fetchResults()로 가져오면 된다.
😀example
// count쿼리가 무조건 나가기 때문에 성능 고려
final QueryResults<Member> results = queryFactory
.selectFrom(member)
.orderBy(member.username.desc().nullsLast())
.offset(7)
.limit(5)
.fetchResults();
assertThat(results.getTotal()).isEqualTo(10); // count 쿼리 전체 개수
assertThat(results.getLimit()).isEqualTo(5); // limit 개수
assertThat(results.getOffset()).isEqualTo(7); // 8번째부터
assertThat(results.getResults().size()).isEqualTo(3); // 8 9 10 3개
- group, having 나머지도 sql문법대로 group, having 사용가능하다. where처럼 체이닝 메서드로 활용해도 되고 ,를 사용하여 여러 파라미터로 넘겨주어도 된다.
😀example
// 1. 기본적인 집합 함수이다. 리턴은 엔티티가 아닌 Tuple로 가능하다. (Tuple은 get으로 값을 꺼낼 수 있다.)
final Tuple tuple = queryFactory
.select(
member.count(),
member.age.sum(),
member.age.avg(),
member.age.max(),
member.age.min()
)
.from(member)
.fetchFirst();
// 2. group, having 사용가능하다.
final List<Tuple> tuples = queryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
.having(member.age.avg().gt(10))
.fetch();
Reference
공식 홈페이지: http://querydsl.com/
공식 레퍼런스:http://querydsl.com/static/querydsl/5.0.0/reference/html_single/
https://www.baeldung.com/querydsl-with-jpa-tutorial
댓글남기기