실전! Querydsl - 섹션3. 기본 문법
CS/김영한 스프링 강의

실전! Querydsl - 섹션3. 기본 문법

기본

@SpringBootTest
@Transactional
public class QuerydslBasicTest {

    @Autowired
    EntityManager em;

    JPAQueryFactory queryFactory;

    @BeforeEach
    public void before() {
        queryFactory = new JPAQueryFactory(em);
        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);
    }

    @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");
    }

    @Test
    public void startQuerydsl() {
        QMember m = new QMember("m");

        Member findMember = queryFactory
                .select(m)
                .from(m)
                .where(m.username.eq("member1")) // 파라미터 바인딩 처리
                .fetchOne();

        assertThat(findMember.getUsername()).isEqualTo("member1");
    }
}

querydsl을 사용함으로써 파라미터 바인딩도 알아서 되고 잘못 작성했을 때 실행할 때 에러가 나는게 아니라 컴파일할 때 에러가 나서 금방 잡을 수 있다.

거기다 저렇게 Q클래스를 생성해서 사용하지만 사실 저럴 필요가 없다.

 

 

 

 

기본값이 뒤에 1 붙는 string이라서 실제 나가는 sql문도 보면 1이 붙는다.

 

 

조건문

실제로 jpql로 잘 번역되서 쌩 sql으로 잘 나간다.

 

 

또 and인 경우에는 굳이 and할 필요 없이 ,하며 쭉 나열하면 and로 인식하여 코드가 좀 더 깔끔해진다.

 

 

결과 조회

보면 getTotal로 전체 갯수를 얻기위해 알아서 count를 한다. count만 해보는 fetchCount도 있다.

하지만 막 조인 들어가고 쿼리가 복잡해지는 단계에선 따로 카운트용 다른 쿼리를 정의하는게 낫다.

 

 

 

정렬

 

 

페이징

전체 조회수가 필요하다면 QueryResults를 사용하자. 이러면 count query도 같이 나간다.

 

 

aggregation 및 groupby도 가능함. 당연히 having도 된다.

 

 

다음은 join

그냥 연관관계 없는것도 양쪽 테이블 다 가져와 억지로 조인하는 세타조인도 지원한다. 물론 억지로 다 가져오면 성능이 엄청 안좋기 때문에 db자체에서 나름 최적화를 한다.

이걸 사용하면 원래 사용하던 외부 조인은 안돼었었지만 이 다음에 설명할 조인 on을 사용하면 외부 조인 사용 가능하다.

조인 연관관계가 있는 경우는 from에서 (member.team, team) 이런식으로 했겠지만 아예 연관관계 자체가 없으니 그냥 (member, team) 이런식으로 나열만 했다.

 

조인 on절. 이 on절을 활용하는 경우는 2가지인데, 하나는 조인 대상 필터링과 연관관계 없는 엔티티 외부 조인

우선 조인 대상 필터링

eq로 teamA인 것만 가져오라고 했기 때문에 teamA만 있고, 없는건 leftjoin을 했으므로 가져왔지만 null로 비워져 있다.

 

만약 그냥 join을 한다면 저 null이 없을 것.

근데 이건 비워져 있는건 고려를 안하고 가져와도 되기 때문에 그냥 where를 써서 거르는 것과 같다. 즉, where로 대체할 수 있다.

 

 

그래서 leftjoin을 쓰는 경우가 아니라면 on보다는 where가 더 익숙하니 이쪽을 사용해도 된다. 이렇게 where로 해도 된다는 의미에서 필터링이라는 이름을 붙인 듯.

 

두번째 경우는 연관관계 없는 엔티티 외부 조인.

join에 member 정보가 없으므로 on만 실행하는걸 볼 수 있다.

좀 헷갈려서 join에서 member도 넣어서 해보고 on도 넣다 안넣었다 해봄. 어려우니 나중에 막힐 때 이런게 있었다며 찾아서 사용하는 용도로 하자.

 

 

 

 

다음은 fetch join. fetch type을 lazy로 했기 때문에 한번에 불러오게 하고 싶으면 fetchjoin을 사용하면 된다.

 

 

쿼리 안에 쿼리가 들어있는 서브쿼리도 JPAExpressions를 사용하면 된다.

 

 

in절도 사용 가능

 

 

한계점은 from절엔 서브쿼리가 안된다는 것. 그냥 jpql이 안된다. 즉 한계점. 우회하거나 네이티브를 써야 한다.

 

 

 

case도 가능

 

 

 

하지만 db에 case를 한다기 보단 앱으로 가져와 하는걸 추천

 

 

상수랑 문자더하기

특이한건 실제 db엔 그냥 안보냄

 

문자열을 그냥 붙일 순 없기에 캐스팅 해야 한다.