Spring-Boot/실전! Querydsl

3. 중급 문법

PHM 2023. 3. 17. 18:11

1. 프로젝션과 결과 반환 - 기본

- 프로젝션 : select 대상 지정

 

프로젝션 대상이 하나

List<String> result = queryFactory
    	.select(member.username)
        .from(member)
        .fetch();

- 프로젝션 대상이 하나면 타입을 명확하게 지정할 수 있음

- 프로젝션 대상이 둘 이상이면 튜플이나 DTO로 조회

 

튜플 조회

- 프로젝션 대상이 둘 이상일 때 사용

- `com.querydsl.core.Tuple`

 

* tuple 도 repository 계층안에서만 쓰는 것을 권장

 

2. 프로젝션과 결과 반환 - DTO 조회

* 순수 JPA에서 DTO 조회 *

- 순수 JPA에서 DTO를 조회할 때는 new 명령어를 사용해야함

- DTO의 package 이름을 다 적어줘야해서 지저분함

- 생성자 방식만 지원함

 

Querydsl 빈 생성(Bean population)

: 결과 DTO 반환할 때 사용, 다음 3가지 방법 지원

 

- 프로퍼티 접근

- 필드 직접 접근

- 생성자 사용

 

필드 직접 접근

- 프로퍼티, 필드 접근 생성 방식에서 이름이 다를 때 해결방안

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

- `username.as("memberName")` : 필드에 별칭 적용

 

생성자 사용

- 타입으로 값을 넣어줌

3. 프로젝션과 결과 반환 - @QueryProjection

- Dto 를 Q파일로 생성해서 사용

- `./gradlew compileQuerydsl`

- `QMemberDto` 생성 확인

 

* QueryProjection 활용 *

List<MemberDto> result = queryFactory
                .select(new QMemberDto(member.username, member.age))
                .from(member)
                .fetch();

- 이 방법은 컴파일러로 타입을 체크할 수 있으므로 가장 안전한 방법이다.

- 다만 DTO QueryDSL 어노테이션을 유지해야 하는 점과 DTO 까지 Q 파일을 생성해야하는 단점이 있다

 

* 순수한 DTO를 유지하고 싶다면 QueryProjection 사용 X

 

* 참고 : distinct 는 JPQL의 distinct 와 같다.

List<String> result = queryFactory
       	 	.select(member.username).distinct()
            	.from(member)
            	.fetch();

 

4. 동적 쿼리 - BooleanBuilder 사용

* 동적 쿼리를 해결하는 두가지 방식 *

- BooleanBuilder

- Where 다중 파라미터 사용

 

 

5. 동적 쿼리 - Where 다중 파라미터 사용

- `where` 조건에 `null` 값은 무시된다.

- 메서드를 다른 쿼리에서도 재활용 할  수 있다.

- 쿼리 자체의 가독성이 높아진다.

 

*조합 가능*

    private BooleanExpression allEq(String usernameCond, Integer ageCond) {
        return usernameEq(usernameCond).and(ageEq(ageCond));
    }

- `null` 체크는 주의해서 처리해야함

 

6. 수정, 삭제 벌크 연산

 

7. SQL function 호출하기

- SQL function은 JPA와 같이 Dialect에 등록된 내용만 호출할 수 있다.