사용 방식은 SQL -> JPQL -> Querydsl 형태로 사용 형태가 달라졌다.

 

Querydsl

  • 정적 타입을 이용해서 SQL과 같은 쿼리를 생성할 수 있도록 하는 프레임워크이다.
  • JPQL처럼 문자열로 작성하지 않고, Querydsl이 제공하는 Fluent API를 이용해서 쿼리를 생성할 수 있다.
  • JPA에서 사용했던 SQL과 비슷하게 생긴 JPQL 조차 사용하지 않는다.
  • 메소드 호출로 쿼리를 수행하기 때문에 오류 발생률도 낮아진다.

JDBC, JPQL과 같은 단순 문자열과 비교해서 Fluent API(Querydsl)를 사용할 때의 장점이 있다.

  1. 코드의 자동 완성 기능을 사용할 수 있다.
  2. 문법적으로 잘못된 쿼리를 허용하지 않는다.
  3. 엔티티 타입과 property를 안전하게 참조할 수 있다.
  4. 엔티티 타입의 리펙토링을 더 잘할 수 있다.

사용 방식은 다음과 같다.

build.gradle에 해당 사항들을 추가한다.

plugins {
  id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

dependencies {
  implementation 'com.querydsl:querydsl-jpa'
}

def querydslDir = "$buildDir/generated/querydsl"

querydsl {
	jpa = true
	querydslSourcesDir = querydslDir
}
sourceSets {
	main.java.srcDir querydslDir
}
configurations {
	querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
	options.annotationProcessorPath = configurations.querydsl
}

위 사항을 추가한 뒤 Gradle -> Tasks -> other -> complieQuerydsl을 사용해서 Q타입을 생성한다.

JPQL -> Querydsl

//JPQL

@PersistenceContext
private EntityManager em;

em.createQuery("select m from Member m", Member.class)
  .getResultList()

----------------------------------------------------------------
//Querydsl

EntityManager em;

JPAQueryFactory query = new JPAQueryFactory(em);

QMember m = new QMember("m");

//select 사용
query.select(m)
     .from(m)
     .fetch();

//selectFrom 사용 : select와 from이 동일하게 사용될 때
query.selectFrom(m)
     .fetch();

Querydsl 메소드 사용

  • .select() : SELECT 절을 의미한다.
  • .selectFrom() : SELECT + FROM을 함께 사용할 수 있다. 해당 내용을 전부 출력할 때 사용된다.
  • .from() : FROM 절을 의미한다.
  • .where(조건 작성)
  • .join("target", "alias") : JOIN절을 의미한다. LEFT, RIGHT, INNER, FETCH 등 다양하게 사용할 수 있다.
  • .on("join의 조건") : join의 조건을 설정한다.
  • .offset() : 몇 번째 row부터 출력할지 설정한다.
  • .limit() : 출력할 행의 수
  • .orderBy() : 정렬 조건 작성
  • .update() : UPDATE 절을 의미한다.
  • .set() : 변경할 조건
  • .delete() : DELETE 절을 의미한다.
  • .execute() : UPDATE, DELETE 실행
  • .fetch() : List 출력
  • .fetchOne() : 엔티티 단건 출력
  • .fetchFirst() : 엔티티 중 첫 번째 출력
  • .fetchResults() : 페이징에서 사용
  • .fetchCount() : count 쿼리 출력

 

중요한 점은 쿼리문을 메소드 형태로 변경했다는 차이만 있을 뿐이다.

 

동적 쿼리를 사용할 때 가능하면 Querydsl을 사용하는 것을 추천한다.