동석쿠
프로그래밍 공부
동석쿠
전체 방문자
오늘
어제
  • 공부 (80)
    • 공부기록 (64)
      • 웹개발 (6)
      • Java (7)
      • cs 공부 (3)
      • http 웹 기본 지식 (8)
      • 자바 스프링 (20)
      • 개인 미니프로젝트 (3)
      • 알고리즘 공부 (6)
      • 면접준비 (2)
      • 프론트공부 (8)
      • 파이썬 플라스크 (1)
    • 항해99 기록 (14)
      • 회고록 (10)
      • 팀프로젝트 (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 프로그래머스
  • 스프링
  • 리액트
  • 리스트
  • JPA
  • Java
  • 상속
  • 리프레쉬토큰
  • 자바스크립트
  • 리프레시토큰
  • Get
  • 알고리즘
  • 항해99
  • API
  • lombok
  • Post
  • 파이썬
  • 자바
  • 스프링부트
  • 문법

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
동석쿠

프로그래밍 공부

공부기록/자바 스프링

Querydsl 공부 <기본 문법>

2022. 6. 7. 19:55

Querydsl공부를 하며 잊지않게 기록하는 게시글 입니다.

 

테스트 기본 코드

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

테스트 전 데이터를 먼저 세팅해준다.

 

JPQL과 Querydsl 비교

@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() {
        Member findMember = queryFactory
                .select(member)
                .from(member)
                .where(member.username.eq("member1"))
                .fetchOne();

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

Querydsl은 JPQL의 빌더 역할을 한다.

Querydsl은 컴파일 시점에서 오류를 발견할 수 있다는 장점이 있다.

 

위위코드에서 JPAQueryFactory를 필드로 사용하였는데, 스프링 프레임워크는 여러 쓰레드에서 동시에 같은 EntityManager에 접근해도, 트랜잭션 마다 별도의 영속성 컨텍스트를 제공하기 때문에 동시성 문제는 걱정하지 않아도 된다.

 

기본 Q타입 활용

Q클래스 인스턴스를 활용하는 두가지 방법

QMember qMember = new QMember("m"); //별칭 직접 지정
QMember qMember = QMember.member; //기본 인스턴스 사용

기본 인스턴스를 static import로 사용

import static study.querydsl.entity.QMember.*

위 검색 예제에선 static import를 사용했다.

 

JPQL이 제공하는 모든 검색 조건

다음과 같은 사용법들이 있다.

member.username.eq("member1") // username = 'member1'
member.username.ne("member1") //username != 'member1'
member.username.eq("member1").not() // username != 'member1'
member.username.isNotNull() //이름이 is not null
member.age.in(10, 20) // age in (10,20)
member.age.notIn(10, 20) // age not in (10, 20)
member.age.between(10,30) //between 10, 30
member.age.goe(30) // age >= 30
member.age.gt(30) // age > 30
member.age.loe(30) // age <= 30
member.age.lt(30) // age < 30
member.username.like("member%") //like 검색
member.username.contains("member") // like ‘%member%’ 검색
member.username.startsWith("member") //like ‘member%’ 검색

또한 and조건을 쉼표로 넘어갈 수 있다.

 

결과 조회

fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환

fetchOne() : 단 건 조회 <결과 없으면 null, 결과 둘 이상이면 com.querydsl.core.NonUniqueResultException>

fetchFirst() : limit(1).fetchOne() 이랑 똑같음

fetchResults() : 페이징 정보 포함, total count 쿼리 추가 실행

fetchCount() : count 쿼리로 변경해서 count 수 조회

fetchResults()의 경우 페이징 쿼리가 복잡해지면 컨텐츠를 가져오는 쿼리랑 실제 토탈카운트를
가져오는 쿼리가 다를 경우가 있다.

복잡하고 성능이 중요한 페이징 쿼리에선 이걸 쓰지말고 쿼리 두개를 따로 날리는게 더 좋다

정렬

desc(), asc() : 일반 정렬

nullsLast(), nullsFirst() : null 데이터 순서 부여

/**
     * 회원 정렬 순서
     * 1. 회원 나이 내림차순(desc)
     * 2. 회원 이름 올림차순(asc)
     * 단 2에서 회원 이름이 없으면 마지막에 출력(nulls last)
     */
    @Test
    public void 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();

        Member member5 = result.get(0);
        Member member6 = result.get(1);
        Member memberNull = result.get(2);

        assertThat(member5.getUsername()).isEqualTo("member5");
        assertThat(member6.getUsername()).isEqualTo("member6");
        assertThat(memberNull.getUsername()).isNull();

    }

페이징

조회 건수 제한

@Test
    public void paging1() {
        List<Member> result = queryFactory
                .selectFrom(member)
                .orderBy(member.username.desc())
                .offset(1)
                .limit(2)
                .fetch();
        assertThat(result.size()).isEqualTo(2);
    }

전체 조회수가 필요할 경우

@Test
    public void paging2() {
        QueryResults<Member> queryResults = queryFactory
                .selectFrom(member)
                .orderBy(member.username.desc())
                .offset(1)
                .limit(2)
                .fetchResults();

        assertThat(queryResults.getTotal()).isEqualTo(4);
        assertThat(queryResults.getLimit()).isEqualTo(2);
        assertThat(queryResults.getOffset()).isEqualTo(1);
        assertThat(queryResults.getResults().size()).isEqualTo(2);
    }

이때 fetchResults()로 인해 count쿼리가 실행된다.

 

집합

집합 함수

@Test
    public void aggregation() {
        List<Tuple> result = queryFactory
                .select(member.count(),
                        member.age.sum(),
                        member.age.avg(),
                        member.age.max(),
                        member.age.min()
                )
                .from(member)
                .fetch();
        Tuple tuple = result.get(0);
        assertThat(tuple.get(member.count())).isEqualTo(4);
        assertThat(tuple.get(member.age.sum())).isEqualTo(100);
        assertThat(tuple.get(member.age.avg())).isEqualTo(25);
        assertThat(tuple.get(member.age.max())).isEqualTo(40);
        assertThat(tuple.get(member.age.min())).isEqualTo(10);
    }

groupBy 예시

/**
     * 팀의 이름과 각 팀의 평균 연령을 구해라.
     */
    @Test
    public void group() throws Exception {
        List<Tuple> result = queryFactory
                .select(team.name, member.age.avg())
                .from(member)
                .join(member.team, team)
                .groupBy(team.name)
                .fetch();

 

'공부기록 > 자바 스프링' 카테고리의 다른 글

Querydsl 공부 <환경 설정 및 기본 엔티티 설정>  (0) 2022.05.26
JPA 연관관계  (0) 2022.04.17
스프링 아이템기능 리팩터링  (0) 2022.03.19
스프링 아이템기능 구현, 단어 뒤집기, 파파고 API  (0) 2022.03.12
스프링 룰렛기능 만들기 (가챠시스템), 자바 난수 설정, 확률설정  (0) 2022.03.09
    '공부기록/자바 스프링' 카테고리의 다른 글
    • Querydsl 공부 <환경 설정 및 기본 엔티티 설정>
    • JPA 연관관계
    • 스프링 아이템기능 리팩터링
    • 스프링 아이템기능 구현, 단어 뒤집기, 파파고 API
    동석쿠
    동석쿠

    티스토리툴바