ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Querydsl 및 간단한 작성방법
    Back-End/Querydsl 2022. 4. 21. 05:49
    728x90

     

    • Querydsl이란, JPQL 빌더라고 할 수 있다.
    • JPA를 사용할 때, 다양한 쿼리 방법을 지원하는데(JPQL, JPA criteria, 네이티브 SQL) 그 중 하나라고 할 수 있다.
    • 여기서 JPQL이란 객체지향 쿼리 언어이다. SQL과 그 형식이 비슷하지만, DB의 테이블에 직접 연결되는 것이 아닌 JPA 엔티티에 대해서 동작을 한다. 그래서 JPQL의 쿼리에는 테이블이 아닌 엔티티에서 표현하고 있는 컬럼의 이름을 써 주어야 한다.

     

    TypedQuery<Member> query = em.createQuery("select m from Member m", Memeber.class);
    List<Member> memberList = query.getResultList();

     

    • 여기서, "select m from Member m" 부분이 JPQL이다. 여기서 Member는 회원 엔티티를 의미하며, DB의 Member 테이블을 의미하는 것이 아니다. JPQL은 DB의 테이블을 전혀 알지 못한다.
    • JPA는 JPQL을 분석하여 적절한 SQL을 만들어서 DB에서 데이터를 조회한다.
    • 의존성에 querydsl을 추가하고, gradle의 task에 있는 compile 작업을 수행하면 build/generated/querydsl 디렉토리에 entity들에 대한 Qclass가 생성이 된다. 이들을 활용하여 쿼리를 작성해낸다.

     

    JPAQueryFactory queryFactory = new JPAQueryFactory(em);
    
    Member findMember = queryFactory
    			.select(m)
                            .from(m)
                            .where(m.username.eq("member1"))
                            .fetchOne();

     

    • JPQL과 달리, querydsl을 사용하면 컴파일 시점에 오류를 잡을 수 있다. 또한 파라미터 바인딩이 더 간단하고 동적 쿼리 작성이 더 간단하다.
    • Qclass 인스턴스를 사용하는 방법은 기본적으로 static하게 만들어져 있어서 QMember.member를 통해 가져와서 사용하면 된다. 추가로 static import를 해 주면 member를 통해 인스턴스를 더 간단하게 사용할 수 있다.

     

    Member findMember = queryFactory
                    .selectFrom(member)
                    .where(
                            member.username.eq("member1"),
                            member.age.between(10,30)
                    )
                    .fetchOne();

    이름이 username이 member1이고 나이가 10~30살인 member를 1개만 가져온다

     

    다음으로 sort가 가능하다.

     

    em.persist(new Member(null, 100));
            em.persist(new Member("member5", 100));
            em.persist(new Member("member6", 100));
            List<Member> result = queryFactory
                    .selectFrom(member)
                    .where(member.age.eq(100))
                    .orderBy(member.age.desc(), member.username.asc().nullsLast())
                    .fetch();

     

    다음으로, join연산이 가능하다.

    List<Member> result = queryFactory
                    .selectFrom(member)
                    .leftJoin(member.team, team)
                    .where(team.name.eq("teamA"))
                    .fetch();

     

    FetchJoin 또한, join이던 left join이던 join뒤에 fetchJoin() 메서드만 붙여주면 된다.

    Member findMember = queryFactory
                    .selectFrom(member)
                    .join(member.team, team).fetchJoin()
                    .where(member.username.eq("member1"))
                    .fetchOne();

    subquery 작성은

    com.querydsl.jpa.JPAExpressions

    이 클래스를 사용하면 된다.

     

    QMember memberSub = new QMember("memberSub");
            List<Member> result = queryFactory
                    .selectFrom(member)
                    .where(member.age.eq(
                            JPAExpressions
                                    .select(memberSub.age.max())
                                    .from(memberSub)
                    ))
                    .fetch();

     

    서브쿼리에서의 alias가 바깥 alias와 겹치면 안 되기 때문에, QMember 인스턴스를 하나 더 생성 해 준다.

    내부 값은 40이 되고, 쿼리가 나가게 된다.

     

    QMember memberSub = new QMember("memberSub");
            List<Member> result = queryFactory
                    .selectFrom(member)
                    .where(member.age.goe(
                            JPAExpressions
                                    .select(memberSub.age.avg())
                                    .from(memberSub)
                    ))
                    .fetch();

     

    다음은 Projection이다. 프로젝션은 select 대상을 지정하는 것으로, 프로젝션 대상이 하나인 경우

     

    List<String> result = queryFactory
                    .select(member.username)
                    .from(member)
                    .fetch();
    
            for (String s : result) {
                System.out.println("s = " + s);
            }

    두 개 이상인 경우, 튜플이나 DTO로 조회한다.

     

    List<Tuple> result = queryFactory
                    .select(member.username, member.age)
                    .from(member)
                    .fetch();
            for (Tuple tuple : result) {
                String username = tuple.get(member.username);
                Integer age = tuple.get(member.age);
    
            }

    댓글

Designed by Tistory.