-
Querydsl 및 간단한 작성방법Back-End/Querydsl 2022. 4. 21. 05:49728x90
- 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); }
'Back-End > Querydsl' 카테고리의 다른 글
엔티티의 1:N 관계에서의 QueryDsl fetch Join - (2) 페이지네이션 해결 방법 (0) 2022.12.27 엔티티의 1:N 관계에서의 QueryDsl fetch Join - (1) 페이지네이션 (0) 2022.12.21