반응형
조건 쿼리
import static com.example.querydsl.entity.QMember.member
public List<Note> findAllMemberByNameAndAge(String username, Integer age) {
return jpaQueryFactory.selectFrom(member)
.where(member.username.eq(username)
.and(member.age.eq(age)))
.fetch();
}
- 검색 조건을 추가(and, or)할 때 체인 형식으로 합니다.
- 파라미터로 null 값이 들어오면 해당
문법
member.username.eq("member") // username = "member"
member.username.ne("member") //username != "member"
member.username.eq("member").not() // username != "member"
member.username.isNotNull() //이름이 is not null
member.username.like("member%") // like 검색
member.username.contains("member") // like :%member%: 검색
member.username.startsWith("member") // like :member%: 검색
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
// 쉼표를 구분자로 파라미터를 추가하는 것은 and()와 같음
where(member.username.eq(username), member.age.eq(age))
결과 조회
- fetch()
- 리스트를 조회
- 데이터가 없으면 빈 리스트 (NOT NULL)
- fetchOne()
- 단 한건 조회
- 데이터가 없으면 Null 조회
- 결과가 둘 이상이면 com.querydsl.core.NonUniqueResultException 예외 발생
- fetchFirst()
- 첫 번째로 발견되는 결과를 조회
- limit(1).fetchOne()과 동일
정렬
- orderBy()를 통한 정렬
- asc() : 오름차순
- desc() : 내림차순
- nullsFirst() : null 데이터인 경우 처음에 결과 출력
- nullsLast() : null 데이터인 경우 마지막에 결과 출력
List<Member> result = jpaQueryFactory
.selectFrom(member)
.where(member.age.between(20,30))
.orderBy(member.age.desc(), member.username.asc().nullsLast())
.fetch();
페이징
페이지 조회 제한
List<Member> result = queryFactory
.selectFrom(member)
.orderBy(member.username.asc())
.offset(0) // 0부터 시작
.limit(5) //
.fetch();
집합
- count() : 카운트 수
- sum() : 합
- avg() : 평균
- max() : 최댓값
- min() : 최솟값
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(10);
assertThat(tuple.get(member.age.sum())).isEqualTo(100);
assertThat(tuple.get(member.age.avg())).isEqualTo(10);
assertThat(tuple.get(member.age.max())).isEqualTo(10);
assertThat(tuple.get(member.age.min())).isEqualTo(10);
- select 해서 가져오는 데이터가 하나인 경우 타입을 명확하게 지정할 수 있지만 타입이 둘 이상이라면 Tuple이나 DTO로 조회해야 한다.
- Tuple은 QueryDsl에서 제공하는 자료구조입니다.
- Tuple로 뽑을 수도 있지만 DTO로 가져올 수도 있습니다.
그룹화
- groupBy()
- having()
List<Tuple> result = jpqQueryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
//.having(member.age.avg().gt(20))
.fetch();
for (Tuple tuple : result) {
System.out.println("tuple = " + tuple);
}
Tuple teamA = result.get(0);
Tuple teamB = result.get(1);
assertThat(teamA.get(team.name)).isEqualTo("teamA");
assertThat(teamA.get(member.age.avg())).isEqualTo(10);
assertThat(teamB.get(team.name)).isEqualTo("teamB");
assertThat(teamB.get(member.age.avg())).isEqualTo(20);
/ * *
* tuple = [teamA, 10.0]
* tuple = [teamB, 20.0]
* /
조인
조인
- join() / innerJoin()
- leftJoin()
- rightJoin()
List<Member> result = jpqQueryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("TeamA"))
.fetch();
// on절 사용
List<Tuple> result = queryFactory
.select(member, team)
.from(member)
.leftJoin(member.team, team)
.on(team.name.eq("TeamA"))
.fetch();
- join의 첫 번째 파라미터
- join 대상을 지정합니다.
- 위 예시 경우, member가 가진 FK를 통해 조인을 합니다. leftJoin(member.team, team)
- 아래 예시 경우, 연관관계가 없는 엔티티를 외부 조인하기 때문에 바로 엔티티를 적어줍니다. leftJoin(team)
→ 전달인자가 달라짐에 주의하자
- join의 두 번째 파라미터
- 첫 번째 파라미터의 별칭을 지정합니다.
- join 뒤에 on절 사용도 가능합니다.
List<Tuple> result = jpaQueryFactory
.select(member,team)
.from(member)
.leftJoin(team)
.on(member.username.eq(team.name))
.fetch();
세타 조인
List<Member> result = jpaQueryFactory
.select(member)
.from(member, team)
.where(member.username.eq(team.name))
.fetch();
- from에 여러 엔티티를 지정하면 됩니다.
페치 조인
Member findMemberByUsername = jpaQueryFactory
.selectFrom(QMember.member)
.join(member.team, team).fetchJoin()
.where(QMember.member.username.eq(username))
.fetchOne();
- JPA에서 성능 최적화를 위해 사용하는 페치 조인 fetchJoin()
서브 쿼리
- JPAExpressions을 이용하여 서브쿼리를 작성합니다.
- JPA JPQL에서는 from 절의 서브쿼리를 지원하지 않기 때문에 QueryDSL도 지원하지 않습니다.
// 서브쿼리를 만들때 alias가 중복되면 안되기 때문에 QMember를 따로 만들어주었습니다.
QMember qMember = new QMember("m");
// 나이가 가장 많은 회원
Member findOldMember = jpaQueryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions
.select(qMember.age.max())
.from(qMember)
))
.fetchOne();
// 나이가 평균 이상이 회원들
List<Member> findMembers = jpaQueryFactory
.selectFrom(member)
.where(member.age.goe(
JPAExpressions
.select(qMember.age.avg())
.from(qMember)
))
.fetch();
Case 문
List<String> result = jpaQueryFactory
.select(member.age
.when(10).then("열살")
.when(20).then("스무살")
.when(30).then("서른살")
.otherwise("기타"))
.from(member)
.fetch();
- CaseBuilder() 이용하여 작성하는 방법
List<String> result = jpaQueryFactory
.select(new CaseBuilder()
.when(member.age.between(0, 13)).then("어린이")
.when(member.age.between(14, 19)).then("청소년")
.otherwise("성인")
)
.from(member)
.fetch();
- case문 응용 - orderyBy 접목
나이가 0~30이 아닌 경우
나이가 0~20인 경우
나이가 21~30인 경우
→ 순서대로 출력
NumberExpression<Integer> rankCase = new CaseBuilder()
.when(member.age.between(0, 20)).then(2)
.when(member.age.between(21, 30)).then(1)
.otherwise(3);
List<Tuple> result = jpaQueryFactory
.select(member.username, member.age, rankCase)
.from(member)
.orderBy(rankCase.desc())
.fetch();
반응형
'Spring Data > Query DSL' 카테고리의 다른 글
QueryDSL Spring Data JPA + 동적 쿼리 (0) | 2023.01.18 |
---|---|
QueryDSL 벌크 쿼리 (0) | 2023.01.16 |
QueryDSL 동적 쿼리 (0) | 2023.01.16 |
QueryDSL DTO에 값 담기 (0) | 2023.01.15 |
QueryDSL Spring Data JPA 같이 적용하기 (0) | 2023.01.14 |