Querydsl - JPQL vs QueryDSL
인프런 실전! Querydsl 강의 내용 정리
오늘은 JPQL과 QueryDSL 코드가 어떻게 다른지 같은 동작하는 메서드를 각각 만들어서 비교해 보자.
먼저 간단하게 테스트 코드를 작성해 보자.
QuerydslBasicTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
@Autowired
EntityManager em;
@BeforeEach
public void before() {
//given
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
em.flush();
em.clear();
}
}
이렇게 미리 사전 작업 해 놓고 이제 JPQL vs Querydsl 을 비교해 보자.
1. JPQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void startJPQL() throws Exception {
//given
//when
String qlString =
"select m from Member m " +
"where m.username = :username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
//then
assertThat(findMember.getUsername()).isEqualTo("member1");
}
2. Querydsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void startQuerydsl() throws Exception {
//given
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QMember m = new QMember("m");
//when
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))
.fetchOne();
//then
assertThat(findMember.getUsername()).isEqualTo("member1");
}
두 개 코드가 어떻게 보이는가?
내가 처음에 느낀 건 querydsl이 초기 세팅 (Q클래스 build) 같은 것만 넘어가면 진짜 사기 같다.
1
2
3
4
.select(m)
.from(m)
.where(m.username.eq("member1"))
.fetchOne();
이건 그냥 SQL 이 아닌가? ㄷㄷ;
그리고 또 하나 좋게 본 건 에러 발생 시점이다.
JPQL에서 만약에 누가
1
2
3
String qlString =
"select m from Member m" +
"where m.username = :username";
이렇게 써 놓으면 오류를 찾을 수 있을 것 같은가?
그런데 querydsl은 무슨 자바 함수 쓰듯이 오타가 나면 바로 IDE 에서 발견 해주고, 놀랍다.

바로 저렇게 나온다.
Querydsl 코드 간소화
이제 Querydsl 코드를 좀 더 줄여 보자.
1
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
이건 메서드 밖으로 던져 버리자.

이렇게 필드로 던졌고, 멀티 쓰레드에 대해 걱정하지 않아도 된다고 한다.
스프링이 어떻게 EntityManager를 관리하는가? 더 궁금하면 이 글을 한번 참고해 보자. 여기서 하는 말을 요약해 보자면,
Spring은
@PersistenceContext를 통해 주입 된EntityManager에 대한 프록시를 제공하여 이 문제를 해결한다고 한다.Spring은
EntityManager빈에 대한 프록시를 생성하고 해당 범위를 관리.이 프록시는
@PersistenceContext주석을 사용할 때 각 스레드가EntityManager의 자체 인스턴스를 얻도록 보장함.
이제 더 줄여 보자.
기본 Q-Type 활용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void startQuerydsl() throws Exception {
//given
QMember m = new QMember("m");
//when
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))
.fetchOne();
//then
assertThat(findMember.getUsername()).isEqualTo("member1");
}
지금 코드는 다음과 같다.

과감하게 QMember m = new QMember("m");를 지워버리고 QMember.member를 바로 사용해 버리자.

자 이제 QMember를 static 처리 해버리면 최종 결과는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
@Test
public void startQuerydsl() throws Exception {
//when
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
//then
assertThat(findMember.getUsername()).isEqualTo("member1");
}
진짜 깔끔해 졌다 ㄷㄷ.
댓글남기기