[JPA] Spring Data JPA와 QueryDSL

DAUN JO·2021년 11월 2일
0

JPA

목록 보기
10/11
post-custom-banner

💡 Spring Data JPA

지루하게 반복되는 CRUD 문제를 세련된 방법으로 해결
개발자는 인터페이스만 작성한다
스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입

📍 사용법

제네릭은 <엔티티, 식별자>로 설정한다.
JpaRepository를 인터페이스 상속 받아 사용하면 된다.
기본적인 CRUD는 구현할 필요가 없다.

메소드 이름으로 Query를 정의하며 @Query 어노테이션을 이용하여 직접 JPQL을 지정할 수 있다.



💡 QueryDSL

SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API


📍 Why?

JPA에서 복잡한 쿼리가 필요한 경우에, JPA 자체 제공 Method만으로 해결하기 어렵기 때문에, Native Query를 고려하게 된다.

이 경우 String값을 직접 이어 붙여가며 작성하기 때문에 복잡하며 오타가 발생할 확률이 높다.

이 쿼리를QueryDSL을 통해 수행할 경우 Native Query의 단점을 극복할 수 있다

먼저 쿼리를 Java로 작성하고 가독성이 좋으며 메소드 타입에 맞지 않는 파라미터를 넘길 경우 컴파일 오류가 발생해 버그를 방지한다.

=> IDE의 도움을,,,, 받을 수 있으며 컴파일 타임에 오류를 잡아 코드 실수를 크게 줄인다. 그리고 제일 큰 이유는 동적 쿼리이다.



📍 Q-type Class

QueryDSL 설정을 마치면 빌드 시 @Entity가 붙은 클래스를 찾아 자동으로 생성된다. 이러한 Q class들을 QueryDSL을 사용하여 메소드 기반으로 쿼리 작성 시 Domain Class의 구조를 설명해주는 메타 데이터 역할을 하며 쿼리의 조건을 설정할 때 사용된다.

일반적으로 Q파일은 Git에 업로드하면 안 된다.



📍 사용법

Entity Manager를 JPAQueryFactory에 넣고 Q클래스 객체를 가지고 쿼리를 Java코드로 짤 수 있다.

검색 조건 쿼리

  • select()

  • from()

  • selcetFrom() (select + from 한번에 처리)

  • where(), and(), or()

  • orderBy()

등..

Member findMember = jpaQueryFactory
                .select(m)
                .from(m)    //selectFrom(m)으로 치환 가능
                .where(m.id.eq(1L)).and(m.age.eq(20))
                .fetchOne();

동일성 체크

  • eq(), ne(), not()
    == , != ,!= (not은 마지막에 붙여준다.)

  • isNotNull()
    Null이 아니면 true


원소, 범위 체크

  • in(1,2,3,4), notIn(1,3,5), between(10,20)
    원소에 있는경우, 원소에 없는경우, 10 ~ 20 사이

  • x.goe(y)
    x >= y

  • x.gt(y)
    x > y

  • x.loe(y)
    x <= y

  • x.lt(y)
    x < y


그 외

  • like()
  • contains()
  • startsWith()

결과 조회

  • fetch()
    리스트 조회 없으면 빈 리스트 반환

  • fetchOne()
    단일 객체 반환, 없으면 null, 둘 이상이면 NonUniqueResultException

  • fetchFirst()
    가장 먼저 찾는걸 반환

  • fetchResults()
    페이징 정보 포함, total 쿼리 추가 실행
    페이징이 아니라면 지양

  • fetchCount()
    count 쿼리로 갯수 조회 (long 타입)


정렬

  • desc(), asc()

  • nullsLast(), nullsFirst()
    null 데이터 순서 부여


예시

  1. age가 18 이상인 member를 출력한다.
  • JPQL
select m from Member m where m.age > 18
  • QueryDSL
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member;

List<Member> memberList = 
	query.selectFrom(m)
		.where(m.age.gt(18))
        .orderBy(m.name.desc())
        .fetch();

  1. 동적 쿼리
    BooleanBuilder에 조건을 넣고 쿼리를 실행시키면 된다. 또한 원하는 필드만 뽑아서 DTO로 export하는 기능도 QueryDSL을 통해 할 수 있다.
String name = "member";
int age = 9;QMember m = QMember.member;BooleanBuilder builder = new BooleanBuilder();
if(name != null) {
    builder.and(m.name.contains(name));
}
if(age != 0) {
    builder.and(m.age.gt(age));
}List<Member> memberList = 
    query.selectFrom(m)
         .where(builder)
         .fetch();



Reference

https://querydsl.com/static/querydsl/4.0.1/reference/ko-KR/html_single/

https://ict-nroo.tistory.com/117

https://zzerosouth.tistory.com/27

profile
🍕
post-custom-banner

0개의 댓글