본문 바로가기
JPA/Querydsl

Querydsl 12 - 동적쿼리와 성능 최적화 조회(where 절 파라미터)

by 킹차니 2022. 1. 22.

 

 

Where절에 파라미터를 사용한 예제

 

이미 이전에 본 방법이다(여기 참고). 리퍼지토리에 아래와 같이 작성가능하다.

public List<MemberTeamDto> search(MemberSearchCondition condition){
    return queryFactory
            .select(new QMemberTeamDto(
                    member.id,
                    member.username,
                    member.age,
                    team.id,
                    team.name
            ))
            .from(member)
            .leftJoin(member.team, team)
            .where(
                    usernameEq(condition.getUsername()),
                    teamNameEq(condition.getTeamName()),
                    ageGoe(condition.getAgeGoe()),
                    ageLoe(condition.getAgeLoe())
            )
            .fetch();
}


private BooleanExpression usernameEq(String username) {
    return hasText(username) ? member.username.eq(username) : null;
}

private BooleanExpression teamNameEq(String teamName) {
    return hasText(teamName) ? team.name.eq(teamName) : null;
}

private BooleanExpression ageGoe(Integer ageGoe) {
    return ageGoe!=null ? member.age.goe(ageGoe) : null;
}

private BooleanExpression ageLoe(Integer ageLoe) {
    return ageLoe!=null ? member.age.loe(ageLoe) : null;
}

위와 같은 방법의 장점은 가독성이 좋고, usernameEq, teamNameEq, ageGoe, ageLoe와 같은 메서드들을 재사용할 수 있다는 것이다.

 

먼저 위의 search메서드를 테스트해보자.

@Test
public void searchTest2(){
    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", 10, teamB);
    Member member4 = new Member("member4", 20, teamB);
    Member member5 = new Member("member5", 55, teamB);
    em.persist(member5);
    em.persist(member1);
    em.persist(member2);
    em.persist(member3);
    em.persist(member4);

    // -- 컨디션 --//
    MemberSearchCondition condition = new MemberSearchCondition();
    condition.setAgeGoe(15);
    condition.setAgeLoe(35); // -> 15~35살
    condition.setTeamName("teamB"); // teamName은 teamB이어야 한다.
    //username 컨디션은 추가하지 않음. 즉 username은 어찌되어도 상관없다는 것이다.
    // -----------

    List<MemberTeamDto> result = repository.search(condition);
    assertThat(result.size()).isEqualTo(1);
    assertThat(result.get(0).getUsername()).isEqualTo("member4");
}

//->테스트 성공

 

이번에는 리터지토리에서 정의한 ageGoe, ageLoe를 재사용하여 ageBetween이라는 메서드를 만들어보자.

private BooleanExpression ageBetween(int ageLoe, int ageGoe) {
    return ageLoe(ageLoe).and((ageGoe(ageGoe)));
}

이렇게 얼마든지 재사용 가능하다.

 

search메서드에서는 MemberTeamDto를 조회하였는데 Member로 조회해야 한다면? 그대로 사용할 수 있다.

public List<Member> searchMember(MemberSearchCondition condition){
    return queryFactory
            .selectFrom(member) //Member조회
            .leftJoin(member.team, team)
            .where(
                    usernameEq(condition.getUsername()),
                    teamNameEq(condition.getTeamName()),
                    ageBetween(condition.getAgeLoe(), condition.getAgeGoe())//ageBetween
            )
            .fetch();
}

 

 

 

 

 

김영한님의 인프런 강의와 PDF를 바탕으로 정리하였습니다.