JPQL (JPA Query Language)
: JPA에서 사용할 수 있는 쿼리
SELECT p FROM 엔티티타입 p WHERE p.엔티티속성 = ?1;
쿼리 메서드
간단한 쿼리문을 작성하기 위해 사용되는 것 (주제 + 서술어)
쿼리 메서드 - 주제 키워드
findBy / readBy / getBy / queryBy / searchBy / streamBy / existsBy
: 조회
existsBy
: 특정 데이터가 존재하는지 확인
- 리턴타입 boolean
countBy
: 쿼리 결과 레코드 개수 리턴
deleteBy / removeBy
: 삭제한 횟수 리턴 또는 리턴 안함
First<number>By / Top<number>By
: 쿼리 조회 결과값 개수 제한
쿼리 메서드 - 조건자 메서드
Is / Equals
: 값의 일치를 조건으로 사용 (생략되는 경우가 많다)
(Is)Not
: 값의 불일치를 조건으로 사용
(Is)Null / (Is)NotNull
: 값이 null인지 검사
(Is)True / (Is)False
: boolean 타입으로 지정된 컬럼값 확인
(Is)GreaterThan / (Is)LessThan / (Is)Between
: 숫자나 datetime 컬럼을 대상으로 한 비교 연산에 사용 (경곗값을 포함하려면 Equal 키워드를 추가)
(Is)StartingWith (StartsWith) / (Is)EndingWith (EndsWith) / (Is)Containg (Contains) / (Is)Like
: 값의 일부를 포함하는 값을 추출할 때 사용
정렬
매개변수를 활용한 쿼리 정렬
productRepository.findByName("펜", Sort.by(Order.asc("price"), Order.desc("stock")));
메서드로 분리하여 작성
private Sort getSort() {
return Sort.by(
Order.asc("price"), Order.desc("stock")
);
}
페이징 처리
리턴타입으로 Page를 설정하고 매개변수는 Pageable 타입 객체 정의
Page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0,2));
of 메서드
// 페이지 번호, 페이지당 데이터 개수, 정렬 방향, 속성(컬럼)
of(int page, int size, Direction, String properties)
페이지 객체 데이터 출력 - 리턴 배열형태
System.out.println(productPage.getContent());
@Query 와 @Param 어노테이션을 사용한 쿼리 작성
- 튜닝된 쿼리를 사용하고자 할 때 직접 SQL을 작성한다.
- 파라미터를 바인딩하는 방식으로 메서드를 구현하면 코드의 가독성이 높아진다.
// 엔티티 타입 리턴
@Query("SELECT p FROM Product p WHERE p.name = :name")
List<Product> findByNameParam(@Param("name") String name);
// 특정 컬럼만 추출하는 쿼리
@Query("SELECT p.name, p.price FROM Product p WHERE p.name = :name")
List<Object[]> findByNameParam(@Param("name") String name);
단점: 컴파일 시점에 에러를 잡지 못하고 런타임 에러가 발생할 수 있다.
이를 해결하기 위해
QueryDSL
: 정접 타입을 이용해 SQL 쿼리를 생성할 수 있도록 하는 프레임워크
Fluent API를 활용해 쿼리를 생성할 수 있다.
장점
- IDE 제공하는 코드 자동 완성 기능을 사용할 수 있다.
- 문법적으로 잘못된 쿼리를 허용하지 않는다.
1) JPAQuery를 활용한 QueryDSL 코드
- from절부터 작성
void queryDslTest() {
// JPAQuery 객체를 EntityManager를 이용해 생성
JPAQuery<Product> query = new JPAQuery(entityManager);
QProduct qProduct = QProduct.product;
// 빌더 형식으로 쿼리 작성
List<Product> productList = query
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch(); // List 타입으로 리턴 받기 위해
}
2) JPAQueryFactory를 활용한 QueryDSL 코드
- select절부터 작성 가능
void queryDslTest() {
JPAQueryFactory<Product> query = new JPAQueryFactory(entityManager);
QProduct qProduct = QProduct.product;
// select 여러개인 경우 Tuple
List<Tuple> productList = query
.select(qProduct.name, qProduct.price)
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch(); // List 타입으로 리턴 받기 위해
}
QueryDSL 컨피그 파일 생성
@Bean 객체로 등록해두면 매번 객체를 초기화하지 않고 스프링 컨테이너에서 가져다 쓸 수 있다.
@Configuration
public class QueryDSLConfiguration {
@PersistenceContext
EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
@Autowired
JPAQueryFactory jpaQueryFactory;
@Test
void queryDslTest() {
QProduct qProduct = QProduct.product;
List<Tuple> productList = jpaQueryFactory
.select(qProduct.name, qProduct.price)
.from(qProduct)
.where(qProduct.name.eq("펜"))
.orderBy(qProduct.price.asc())
.fetch(); // List 타입으로 리턴 받기 위해
}
'개발공부 > JAVA Spring' 카테고리의 다른 글
[Spring Boot] JPA 영속성 전이 cascade, 고아객체 (0) | 2023.03.27 |
---|---|
[Spring Boot] JPA Auditing (0) | 2023.03.11 |
[Spring Boot] Redis config (0) | 2023.03.10 |
shorten url (0) | 2023.03.06 |
[Spring Boot] 테스트 코드 작성 관련 정리 (0) | 2023.03.03 |
댓글