Spring/Spring Data JPA

[자바 ORM 표준 JPA 프로그래밍] 10-4. 객체지향 쿼리 언어: QueryDSL (1)

noahkim_ 2024. 8. 2. 11:11

김영한 님의 "자바 ORM 표준 JPA 프로그래밍" 책을 정리한 포스팅 입니다.

 

1. QueryDSL

  • Java에서 쿼리를 생성할 수 있게 해주는 프레임워크 (오픈소스)

 

특징

타입 안전
  • 자바 코드 O (문자열 기반 X)
  • 컴파일 시점에 타입 체크

 

동적 쿼리 생성
Fluenct API (Method Chaining)
  • 직관적인 쿼리 작성 방식 (Readable)

 

다양한 지원
  • SQL, JPA, MongoDB, Lucense

 

2. 시작

Q Class

  • metadata (entity field)
  • entity-based
  • (plugin) querydsl-apt 

 

JPAQuery (or JPAQueryFactory)

  • type-safe query
  • dynamically
public class UserRepositoryCustomImpl implements UserRepositoryCustom {

    @PersistenceContext
    private EntityManager em;

    @Override
    public List<User> findByCustomPredicate(String firstname) {
        JPAQuery query = new JPAQuery(em);
        QMember member = QMember.member;

        List<Member> members = query.from(member)
                            .where(member.username.eq(firstname))
                            .list(member);
    }
}

 

3. 검색 조건

Where

JPAQuery query = new JPAQuery(em);
QItem item = QItem.item;

List<Item> list = query.from(item)
                       .where(item.name.eq("좋은상품").and(item.price.gt(20000)))
                       .list(item);  //조회할 프로젝션 지정

 

OrderBy + Offset

QItem item = QItem.item;

List<Item> list = query.from(item)
                       .where(item.price.gt(20000))
                       .orderBy(item.price.desc(), item.stockQuantity.asc())
                       .offset(10).limit(20)
                       .list(item);

 

QueryModifiers 
  • (parameter) limit, offset
QueryModifiers queryModifiers = new QueryModifiers(20L, 10L);  //limit, offset;

List<Item> list = query.from(item)
                       .restrict(queryModifiers)
                       .list(item);

 

 

4. 조회

uniqueResult()
  • 조회 결과가 한 건일 경우
  • NonUniqueResultException (한건 이상)

 

singleResult()
  • 조회 결과가 한 건일 경우
  • 한 건 이상일 경우, 처음 데이터 반환

 

list()
  • 결과가 하나 이상일 때
  • 결과 없을 경우, 컬렉션 반환

 

5. 페이징

listResults()
  • 데이터 + 페이징 정보
SearchResults<Item> result = query.from(item)
                                  .where(item.price.gt(10000))
                                  .offset(10).limit(20)
                                  .listResults(item);                                 

long total = result.getTotal();  //검색된 전체 데이터 수
long limit = result.getLimit();
long offset = result.getOffset();
List<Item> results = result.getResults();  //조회된 데이터

 

6. 그룹

List<Item> list = query.from(item)
                       .groupBy(item.price)
                       .having(item.price.gt(10000))
                       .list(item);