1. QueryDSL(Query Domain Specific Language) 이란?
- JPA에서는 @Query를 이용해서 애플리케이션에서 사용할 쿼리를 관리한다. 하지만 @Query로 등록한 쿼리는 프로젝트가 로딩되는 시점에 파싱되기 때문에 고정된 SQL만 사용할 수 있다.
- 동적으로 쿼리를 처리하려면 QueryDSL을 이용한다.
- 복잡한 검색 조건이나 조인, 서브 쿼리 등의 기능도 구현이 가능하다.
- QueryDSL은 오픈소스 프로젝트로서 쿼리를 문자열이 아닌 자바 코드로 작성할 수 있도록 지원하는일종의 JPQL 빌더이다.
- 엔티티 클래스를 그대로 이용하는 것이 아닌 'Q 도메인' 이란 것을 이용해야한다.
- Querydsl 라이브러리를 이용해서 엔티티 클래스를 Q도메인 클래스로 변환해야 한다.
2. Querydsl
- 제목/내용/작성자 하나의 항목으로 검색하는 경우
- 제목 + 내용 같이 2개의 항목으로 검색하는 경우
- 제목 + 내용 + 작성자와 같이 3개의 항목으로 검색하는 경우
3. 사용법
- BooleanBuilder를 생성한다.
- 조건에 맞는 구문은 Querydsl에서 사용하는 Predicate 타입의 함수를 생성한다.
- BooleanBuilder에 작성된 Predicate를 추가하고 실행한다.
4. 특징
- Querydsl 준비 - 동적 처리를 위해 Q도메인 클래스를 가져옴
- 엔티티 클래스에 선언된 필드를 변수로 사용할 수 있음
* 사용 예제
// 제목에 21이란 글자가 있는 엔티티들을 검색하기
@Test
public void testQuery1()
{
Pageable pageable = PageRequest.of(0, 10, Sort.by("gno").descending());
// 1. 동적 처리를 위해 Q도메인 클래스를 얻어옴
// - Q도메인 클래스를 이용하면 엔티티 클래스에 선언된 title, content같은 필드들을 변수로 활용할 수 있다.
QGuestbook qGuestbook = QGuestbook.guestbook;
String keyword = "21";
// 2. where 문에 들어가는 조건들을 넣어주는 컨테이너 역할을 수행
BooleanBuilder builder = new BooleanBuilder();
// 3. 원하는 조건은 필드 값과 같이 결합해서 생성.
// - BooleanBuilder 안에 들어가는 값은 Predicate 타입을 사용
BooleanExpression expression = qGuestbook.title.contains(keyword);
// 4. 만들어진 조건은 where문에 and나 or 같은 키워드와 결합
builder.and(expression);
// 5. BooleanBuilder는 GuestbookRepository에 추가된 QuerydslPredicateExcutor 인터페이스의 findAll()을 사용할 수 있음
Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);
System.out.println("================testQuery1=============");
result.stream().forEach(guestbook -> {
System.out.println(guestbook);
});
}
// 다중 항목 검색
@Test
public void testQuery2()
{
Pageable pageable = PageRequest.of(0, 10, Sort.by("gno").ascending());
QGuestbook qGuestbook = QGuestbook.guestbook;
String keyword = "1";
BooleanBuilder builder = new BooleanBuilder();
BooleanExpression exTitle = qGuestbook.title.contains(keyword);
BooleanExpression exContent = qGuestbook.content.contains(keyword);
BooleanExpression exAll = exTitle.or(exContent);
builder.and(exAll);
builder.and(qGuestbook.gno.gt(15L));
Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);
System.out.println("================testQuery2=============");
result.stream().forEach(guestbook -> {
System.out.println(guestbook);
});
}