2 분 소요

인프런 실전! 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");  
}

진짜 깔끔해 졌다 ㄷㄷ.

태그: ,

카테고리:

업데이트:

댓글남기기