JPQL
JPA Query Language 의 줄임말로 JPA에서 사용할 수 있는 쿼리
엔티티 객체를 대상으로 수행하는 쿼리
매핑된 엔티티의 이름과 필드의 이름을 사용
쿼리 메서드의 생성
쿼리 메서드는 주제(Subject)와 서술어(Predicate)로 구분
' find...By ', ' exists...By ' 와 같은 키워드로 쿼리의 주제를 정하며, ' By '는 서술어의 시작을 나타내는 구분자 역할을 함.
서술어 부분은 검색 및 정렬 조건을 지정하는 영역 / 엔티티의 속성으로 정의할 수 있고, AND 나 OR 를 사용해서 조건을 확장하는 것도 가능.
// (리턴타입) + {주제 + 서술어(속성)}
List<Customer> findByEmailAndName(String email, String name);
쿼리 메서드의 주제 키워드
- find...By
- read...By
- get...By
- query...By
- search...By
- stream...By
' ... ' 표시 영역 : 도메인 (엔티티) 표현 가능
→ 리포지토리에서는 도메인 설정 후 메서드를 사용하기 때문에 중복으로 판단해 생략함.
키워드 | 키워드 설명 | 리턴타입 | SQL |
exists...By | 특정 데이터 존재 여부 | boolean | IF(EXISTS (SELECT ~ WHERE EXISTS (SELECT ~ |
count...By | 레코드 개수 반환 | 숫자(long) | SELECT COUNT(*) |
delete...By remove...By |
삭제 쿼리 | 리턴타입 없음 삭제한 횟수 |
DELETE FROM TABLE ~ |
...First<number>... Top<number> |
결과값 개수 제한 | 여러건 조회 | LIMIT 1 TOP (1) |
쿼리 메서드의 조건자 키워드
키워드 | 키워드 설명 | SQL |
Is(=is) | 값 일치를 조건 | WEHRE ITEM = |
(Is)Not | 값 불일치 조건 | WHERE ITEM <> 'FF' WHERE ITEM != 'SS' |
(Is)Null (Is)NotNull |
null 인지 검사 | WHERE IS NULL WEHRE IS NOT NULL |
(Is)True (Is)False |
boolean 타입으로 지정된 컬럼값 확인 |
|
And Or |
여러개의 조건으로 묶을 때 | WHERE ITEM = AND (OR) ITEM2 = |
(Is)GreaterThen (Is)GreaterThenEqual (Is)LessThen (Is)Between |
비교 연산 사용 | WEHRE NUMBER > WHERE NUMBER >= WHERE NUMBER < WEHRE NUMBER BETWEEN AND |
(Is)StartingWith(= StartsWith) (Is)EndingWith(= EndsWith) (Is)Containing(= Contains) (Is)Like |
컬럼값 일부 일치 여부 Like는 ' % ' 명시적 |
WEHRE ITEM LIKE '%S' WEHRE ITEM LIKE 'S%' WHERE ITEM LIKE '%S%' WEHRE ITEM LIKE (명시적)'%S' |
정렬과 페이징 처리
- 정렬 처리
/*
Asc - 오름차순, Desc - 내림차순
*/
// 고객정보를 이메일로 검색 후 id로 오름차순 정렬
List<Customer> findByEmailOrderByidAsc(String email);
// 고객정보를 이메일로 검색 후 id로 내림차순 정렬
List<Customer> findByEmailOrderByidDesc(String email);
-------
/*
정렬 기준 여러개 사용
*/
// 고객정보를 이메일로 검색 후 id기준으로 오름차순 정렬후 Name기준으로 내림차순 정렬
List<Customer> findByEmailOrderByidAscNameDesc(String email);
-------
/*
위와 같이 사용하면 메서드의 이름이 길어져 가독성↓
매개변수를 활용한 쿼리 정렬
*/
List<Customer> findByEmail(String email, Sort sort);
/*
테스트 시 작성 코드
Sort 클래스는 Order 객체를 활용해 정렬 기준 생성
여러기준을 사용 할 경우 ' , ' 사용
*/
customerRepository.findByEmail(email, Sort.by(Order.asc("id")));
customerRepository.findByEmail(email, Sort.by(Order.asc("id"), Order.desc("Name")));
- 페이징 처리
페이징이란 데이터베이스의 레코드를 개수로 나눠 페이지를 구분하는 것
25개의 레코드가 있다면 7개씩 총 4개의 페이지로 구분하고 특정 페이지를 가져올 수 있음
/*
페이징 처리 메서드
*/
// 리턴 타입 : Page, 매개변수 : Pageable 타입 객체
Page<Customer> findByEmail(String email, Pageable pageable);
/*
호출 시
PageRequest 는 Pageable 구현체임
PageRequest 는 of 메서드를 통해 객체 생성
*/
Page<Customer> customerPage = customerRepository.findByEmail(email, PageRequest.of(0, 2));
@Query 어노테이션 사용
다른 데이터베이스로 변경할 일이 없다면
직접 SQL을 작성 할 수 있음. 주로 튜닝된 쿼리를 사용하고자 작성
/*
@Query 어노테이션 사용 메서드
*/
@Query("SELECT EMAIL FROM CUSTOMER AS CT WEHRE CT.EMAIL = ?1")
List<Customer> findByEmail(String email);
/*
위 쿼리는 파라미터의 순서가 바뀌면 오류 발생 가능성 ↑
@Param 어노테이션 사용
*/
@Query("SELECT EMAIL FROM CUSTOMER CT WEHRE CT.EMAIL = :email")
List<Customer> findByEmailParam(@Param("email") String email);
QueryDSL 적용
정적 타입을 이용해 SQL과 같은 쿼리를 생성할 수 있도록 지원하는 프레임워크
플루언트(Fluent) API를 활용해 쿼리 생성
개인적인 생각으로는 C# LINQ 와 비슷
- QueryDSL 의 장점
- IDE가 제공하는 코드 자동 완성 기능 사용 가능
- 잘못된 쿼리 허용하지 않음. 문법 오류 발생 없음
- 동적 쿼리 생성 가능
- 가독성 및 생산성 ↑
- 도메인 타입과 프로퍼티를 안전하게 참조 가능
- QueryDSL 의 단점
- QueryDSL 구문과 그 개념 및 제한 사항을 숙지해야함
- 모든 데이터베이스의 고급 기능을 지원하지 않을 수 있음
- 새 라이브러리를 추가해야하므로 오버헤드가 증가 할 수 있음
라이브러리 업데이트 시 상당한 코드 변경이 있을 수 있음 - 디버깅이 어려움
- 복잡한 쿼리의 경우 생성 및 실행 시간이 길어 질 수 있음
QueryDSL 을 사용하려면 의존성을 추가 후 APT 플러그인을 추가해야함.
'북 스터디 > 스프링 부트 핵심가이드' 카테고리의 다른 글
유효성 검사와 예외처리 (0) | 2023.04.16 |
---|---|
연관관계 매핑 (0) | 2023.04.09 |
데이터베이스 연동 - 2 (0) | 2023.03.26 |
데이터베이스 연동 - 1 (0) | 2023.03.25 |
스프링 부트 개발하기 / API 작성 (0) | 2023.03.19 |