목차
📝 개요
QueryDSL에서 제공하는 검색 조건에 대해 알아보자!!
기본 검색 조건 쿼리
@Test
public void search() {
Member findMember = queryFactory
.selectFrom(member)
.where(member.username.eq("member1")
.and(member.age.eq(10)))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
📌 검색 조건
코드 |
기능 |
member.username.eq("member1") |
username = 'member1' |
member.username.ne("member1") |
username != 'member1' |
member.username.isNotNull() |
이름이 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) |
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%") |
like 검색 |
member.username.contains("member") |
like ‘%member%’ 검색 |
member.username.startsWith("member") |
like ‘member%’ 검색 |
📌 결과 조회
코드 |
기능 |
fetch() |
리스트 조회, 데이터 없으면 빈 리스트 반환 |
fetchOne() |
단 건 조회 |
fetchFirst() |
처음 한 건 조회 |
fetchResults() |
페이징 정보 포함, total count 쿼리 추가 실행 |
fetchCount() |
count 쿼리로 변경해서 count 수 조회 |
//List
List<Member> fetch = queryFactory
.selectFrom(member)
.fetch();
//단 건
Member findMember1 = queryFactory
.selectFrom(member)
.fetchOne();
//처음 한 건 조회
Member findMember2 = queryFactory
.selectFrom(member)
.fetchFirst();
//페이징에서 사용
QueryResults<Member> results = queryFactory
.selectFrom(member)
.fetchResults();
//count 쿼리로 변경
long count = queryFactory
.selectFrom(member)
.fetchCount();
📌 정렬
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(100))
.orderBy(member.age.desc(), member.username.asc().nullsLast())
.fetch();
- nullsLast()
- null 값을 정렬 결과 마지막에 위치시킨다.
- nullsFirst()
- null 값을 정렬 결과의 처음에 위치시킨다.
📌 페이징
@Test
public void paging1() {
List<Member> result = queryFactory
.selectFrom(member)
.orderBy(member.username.desc())
.offset(1) //0부터 시작(zero index)
.limit(2) //최대 2건 조회
.fetch();
assertThat(result.size()).isEqualTo(2);
}
📌 집합
코드 |
기능 |
member.count() |
회원 수 |
member.age.sum() |
나이 합 |
member.age.avg() |
평균 나이 |
member.age.max() |
최대 나이 |
member.age.min() |
최소 나이 |
@Test
public void aggregation() throws Exception {
List<Tuple> result = queryFactory
.select(member.count(),
member.age.sum(),
member.age.avg(),
member.age.max(),
member.age.min())
.from(member)
.fetch();
Tuple tuple = result.get(0);
assertThat(tuple.get(member.count())).isEqualTo(4);
assertThat(tuple.get(member.age.sum())).isEqualTo(100);
assertThat(tuple.get(member.age.avg())).isEqualTo(25);
assertThat(tuple.get(member.age.max())).isEqualTo(40);
assertThat(tuple.get(member.age.min())).isEqualTo(10);
}
📌 조인
코드 |
기능 |
join(), innerJoin() |
내부조인 |
leftJoin(0 |
left 외부조인 |
rightJoin() |
right 외부조인 |
@Test
public void join() throws Exception {
QMember member = QMember.member;
QTeam team = QTeam.team;
List<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("teamA"))
.fetch();
assertThat(result)
.extracting("username")
.containsExactly("member1", "member2");
}
📌세타 조인
@Test
public void theta_join() throws Exception {
em.persist(new Member("teamA"));
em.persist(new Member("teamB"));
List<Member> result = queryFactory
.select(member)
.from(member, team)
.where(member.username.eq(team.name))
.fetch();
assertThat(result)
.extracting("username")
.containsExactly("teamA", "teamB");
}
📌조인 대상 필터링 - On절
- On절은 조인 대상을 필터링해서 지정할 수 있다.
@Test
public void join_on_filtering() throws Exception {
List<Tuple> result = queryFactory
.select(member, team)
.from(member)
.leftJoin(member.team, team).on(team.name.eq("teamA"))
.fetch();
for (Tuple tuple : result) {
System.out.println("tuple = " + tuple);
}
}
📌 페치 조인
- 페치조인은 SQL에서 제공하는 기능이 아니다. SQL 조인을 활용하여 연관된 엔티티를 SQL 한번에 조회하는 기능이다. 주로 최적화에 사용된다.
@Test
public void fetchJoinUse() throws Exception {
em.flush();
em.clear();
Member findMember = queryFactory
.selectFrom(member)
.join(member.team, team).fetchJoin()
.where(member.username.eq("member1"))
.fetchOne();
boolean loaded = emf.getPersistenceUnitUtil().isLoaded(findMember.getTeam());
assertThat(loaded).as("페치 조인 적용").isTrue();
}
- 사용 방법은 join() 뒤에 fetchJoin()을 추가하면 된다.
📌서브쿼리
- 서브 쿼리는 SQL에서 사용하는 다중 쿼리 문이다.
- 사용 방식만 기억해두자
@Test
public void subQuery() throws Exception {
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions
.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
assertThat(result).extracting("age").containsExactly(40);
}
📌Case 문
List<String> result = queryFactory
.select(new CaseBuilder()
.when(member.age.between(0, 20)).then("0~20살")
.when(member.age.between(21, 30)).then("21~30살")
.otherwise("기타"))
.from(member)
.fetch();