[Spring Boot] Querydsl

SeoYoung Jung·2022년 4월 15일
0

Querydsl? JPQL?

Querydsl은 JPQL 빌더
JPQL: 문자(실행 시점 오류), Querydsl: 코드(컴파일 시점 오류)
JPQL: 파라미터 바인딩 직접, Querydsl: 파라미터 바인딩 자동 처리

JPAQueryFactory?

JPAQueryFactory queryFactory;

Querydsl을 사용하기 위한 객체생성!

조건생성시 = 검색 조건은 .and() , . or() 를 메서드 체인으로 연결
select+ from = selectfrom 가능

제공 연산자

member.username.eq("member1") // username = 'member1'
member.username.ne("member1") //username != 'member1'
member.username.eq("member1").not() // 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 ‘m

Fetch 종류

fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환
fetchOne() : 단 건 조회
결과가 없으면 : null
결과가 둘 이상이면 : com.querydsl.core.NonUniqueResultException
fetchFirst() : limit(1).fetchOne()
fetchResults() : 페이징 정보 포함, total count 쿼리 추가 실행
fetchCount() : count 쿼리로 변경해서 count 수 조회

*정렬 종류

desc() , asc() : 일반 정렬
nullsLast() , nullsFirst() : null 데이터 순서 부여

*조인

join(조인 대상, 별칭으로 사용할 Q타입)
join() , innerJoin() : 내부 조인(inner join)
leftJoin() : left 외부 조인(left outer join)
rightJoin() : rigth 외부 조인(rigth outer join)
JPQL의 on 과 성능 최적화를 위한 fetch 조인 제공

세타조인 - 연관관계가 없는 필드로 조인
= from 절에 여러 엔티티를 선택해서 세타 조인
외부 조인 불가능 다음에 설명할 조인 on을 사용하면 외부 조인 가능

!!: on 절을 활용해 조인 대상을 필터링 할 때, 외부조인이 아니라 내부조인(inner join)을 사용하면,

where 절에서 필터링 하는 것과 기능이 동일하다. 따라서 on 절을 활용한 조인 대상 필터링을 사용할 때,
내부조인 이면 익숙한 where 절로 해결하고, 정말 외부조인이 필요한 경우에만 이 기능을 사용

주의!

문법을 잘 봐야 한다. leftJoin() 부분에 일반 조인과 다르게 엔티티 하나만 들어간다.

일반조인: leftJoin(member.team, team)
on조인: from(member).leftJoin(team).on(xxx)

from 절의 서브쿼리 한계

JPA JPQL 서브쿼리의 한계점으로 from 절의 서브쿼리(인라인 뷰)는 지원하지 않는다. 당연히 Querydsl
도 지원하지 않는다. 하이버네이트 구현체를 사용하면 select 절의 서브쿼리는 지원한다. Querydsl도
하이버네이트 구현체를 사용하면 select 절의 서브쿼리를 지원한다.

from 절의 서브쿼리 해결방안

  1. 서브쿼리를 join으로 변경한다. (가능한 상황도 있고, 불가능한 상황도 있다.)
  2. 애플리케이션에서 쿼리를 2번 분리해서 실행한다.
  3. nativeSQL을 사용한다.

Case 문

select, 조건절(where), order by에서 사용 가능

프로젝션 - 뭘 가져올지 정하는것!

대상 1개 - 타입 확실
대상 그이상 -튜블이나 DTO로 정하기

tuple -쿼리 dsl 이 여러개 조회할때 미리 만들어논 타입

  • 사실 많이쓰진않는다.

DTO로 결과를 더 많이 반환..

JPQL
순수 JPA에서 DTO를 조회할 때는 new 명령어를 사용해야함
DTO의 package이름을 다 적어줘야해서 지저분함
생성자 방식만 지원
생성자는 type을 보고 들어가야한다.

ExpressionUtils.as(source,alias) : 필드나, 서브 쿼리에 별칭 적용
username.as("memberName") : 필드에 별칭 적용

프로젝션 결과 반환 가짓수

1.Setter
2.field
3.Constructor

@QueryProjection

=이 어노테이션 사용시 dto도 q파일로 생성 가능하다.
=이 방법은 컴파일러로 타입을 체크할 수 있으므로 가장 안전한 방법

- 동적 쿼리

1.boolean bulider 사용

BooleanBuilder builder = new BooleanBuilder();
=>

  1. Where 다중 파라미터 사용

서브쿼리

com.querydsl.jpa.JPAExpressions 사용

수정, 삭제 벌크 연산

=같은 연산을 한번에 처리하는 것

SQL function 호출하기

=SQL function은 JPA와 같이 Dialect에 등록된 내용만 호출

순수 JPA 리포지토리와 Querydsl

JPAQueryFactory 를 스프링 빈으로 등록해서 주입받아 사용해도 된다

동적 쿼리와 성능 최적화 조회 - Builder 사용, where 조건절 사용

조회 API 컨트롤러 개발

인터페이스 지원 - QuerydslPredicateExecutor

문제 3가지 querydsl문 작성하기
<검증 x>
team a, b,c//member1,2,3
생성자 작성 필요없음

  1. 팀B에 소속된 모든 회원을 구하시오

학교a,b,c //학생 1,2,3,4
2.각 학교의 이름과 각 학교별 학생 몸무게 평균, 키 평균 구하기

서브쿼리 작성 문제
3. 학생 중 최대 몸무게 가진 학생 이름 섭쿼리로 작성하세요
4.멤버 평균 나이가 최소와 같은 멤버를 구하는 섭쿼리 작성


  1. List result = queryFactory
    .select(team.name, member.age.avg())
    .from(member)
    .join(member.team, team)
    .groupBy(team.name)
    .fetch();
  2. List result = queryFactory
    .select(school.name, student.height.avg())
    .from(student)
    .join(school.student, student)
    .groupBy(school.name)
    .fetch();
  3. List result = queryFactory
    .select(Student.studentname,
    JPAExpressions
    .select(StudentSub.weight.max()))
    .from(studentSub)
    .from(student)
    .fetch(); 4.List result = queryFactory
    .selectFrom(member)
    .where(member.age.eq(
    JPAExpressions
    .select(memberSub.age.min())
    .from(memberSub)
    ))
    .fetch();
profile
뚱땅뚱땅개발자

0개의 댓글