Query DSL게시글은 대부분 인프런의 김영한님의 강의인 '실전! Query DSL' 기반으로 내용을 정리했습니다.
JPQL vs QueryDSL
엔티티 찾기
JPQL로 엔티티 하나를 찾아오려면 아래와 같이 작성하면 된다.
@Test
public void startJPQL() {
// member1 찾기
String qlString = "select m from Member m where m.username=:username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
QueryDSL로 엔티티를 하나 찾아오려면 아래와 같이 작성하면 된다.
@Test
public void startQuerydsl() {
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QMember m = new QMember("m"); // 어떤 Q 멤버인지 구분하는 이름
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
QueryDSL에서는 JPAQueryFactory를 이용해서 쿼리와 관련된 코드를 작성하므로 필수이다. 그리고 new QMember에 들어가는 파라미터는 어떤 Q 멤버인지를 구분하는 이름이긴하나 나중에 굳이 사용안해도 할 수 있는 법이 있으므로 그냥 구분하는 이름이라고 알면 될 거 같다.
JPQL과 QueryDSL로 작성한 코드는 같은 기능을 하고 있지만 차이점이 존재한다. 눈에 보이는 큰 차이점은 코드이다. JPQL은 String에 쿼리를 작성하고, QeuryDSL은 자바와 비슷하게 작성할 수 있다. 그리고 JPQL에서는 파라미터 바인딩을 직접 명시해줬지만 QueryDSL에서는 명시하지 않았다. QueryDSL에서는 파라미터 바인딩을 자동으로 처리해준다. 마지막으로 둘의 결정적인 큰 차이점은 JPQL 쿼리문에 오타나 문법에 맞지 않은 쿼리를 작성했을 시 에러가 나는 시점은 이 JPQL이 호출되어야 에러가 난다(Runtime 에러). 그에 반해 QueryDSL에 오타나 잘못 작성할 경우 애플리케이션을 실행하자마자 에러가 떠버린다(Compile 에러). 그래서 개발자가 애플리케이션을 실행하기만해도 에러가 발생해 에러를 더 잘 캐치할 수 있다.
정리하자면
- JPQL : String / QueryDsL : 코드
- JPQL : 런타임 에러 / QueryDSL : 컴파일 에러
- JPQL : 파라미터 바인딩 명시 작성 / QueryDSL : 파라미터 바인딩 자동 처리
JPQueryFactory 수정
QueryDSL로 작성한 코드를 조금 더 줄여보자.
JPAQueryFactory는 필드 쪽으로 빼도 괜찮다.
@Autowired
EntityManager em;
JPAQueryFactory queryFactory;
@BeforeEach
public void before() {
queryFactory = new JPAQueryFactory(em);
// ... 생략
동시성 문제가 생길 것 같지만 EntityManager 자체가 동시성, 즉 멀티스레드에 아무 문제 없게 설계되어 있기 때문에 개발자가 신경 쓸 필요가 없다.