본문 바로가기
Spring/QueryDSL

동적 쿼리 - BooleanBuilder

by 개복이 2021. 6. 13.

[BooleanBuilder]

  • QueryDSL에서 동적 쿼리를 해결하는 방식에는 크게 두 가지가 있습니다..
    • BooleanBuilder
    • Where Parameter
  • 먼저 BooleanBuilder에 대해서 소개하겠습니다..

 

[MemberTeamDto]

  • @QueryProjection을 사용하면 작성한 DTO Class를 Q타입으로 생성합니다..
  • @QueryProjection을 사용하지 않고 Projections.Constructor 등을 사용하여 작성하셔도 됩니다..
@Data
public class MemberTeamDto {
    private Long memberId;
    private String username;
    private int age;
    private Long teamId;
    private String teamName;
    
    @QueryProjection
    public MemberTeamDto(Long memberId, String username, int age, Long teamId, String teamName){
        this.memberId = memberId;
        this.username = username;
        this.age = age;
        this.teamId = teamId;
        this.teamName = teamName;
    }
}

 

[MemberSearchCondition]

  • 검색 조건으로 넘겨받을 MemberSearchCondition Class를 작성합니다..
  • 여기서는 username, teamName, ageGoe, ageLoe 파라미터를 받습니다..
@Data
public class MemberSearchCondition {

    private String username;
    private String teamName;
    private Integer ageGoe;
    private Integer ageLoe;
    
}

 

[searchByBooleanBuilder]

  • BooleanBuilder를 사용하여 검색 조건을 추가해줍니다..
public List<MemberTeamDto> searchByBooleanBuilder(MemberSearchCondition condition){
    
    // 검색조건 추가
    BooleanBuilder builder = new BooleanBuilder();
    if(StringUtils.hasText(condition.getUsername())){
        builder.and(member.username.eq(condition.getUsername()));
    }
    if(StringUtils.hasText(condition.getTeamName())){
        builder.and(team.name.eq(condition.getTeamName()));
    }
    if(condition.getAgeGoe() != null){
        builder.and(member.age.goe(condition.getAgeGoe()));
    }
    if(){
        builder.and(member.age.loe(condition.getAgeLoe()));
    }
    
    return queryFactory
           .select(new QMemberTeamDto(
                   member.id.as("memberId"),
                   member.username,
                   member.age,
                   team.id.as("teamId"),
                   team.name.as("teamName")
           ))
           .from(member)
           .leftJoin(member.team, team)
           .where(builder)
           .fetch();
}

 

[Test 검증]

@Test
void searchByBooleanBuilderTest(){
    // teamA, teamB 생성
    Team teamA = new Team("teamA");
    Team teamB = new Team("teamB");
    em.persist(teamA);
    em.persist(teamB);
    
    // member1, member2, member3, member4 생성
    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);
    
    // 검색조건 추가
    MemberSearchCondition condition = new MemberSearchCondition();
    condition.setAgeGoe(35);
    condition.setAgeLoe(40);
    condition.setTeamName("teamB");
    
    List<MemberTeamDto> result = memberJpaRepository.searchByBooleanBuilder(condition);
    assertThat(result).extracting("username").containsExactly("member4");
}

 

  • 검색 조건(age >= 35, age <= 40, teamName = teamB)이 where 절에 동적으로 추가된 것을 확인할 수 있습니다..

 

  • 그렇다면 검색 조건이 없을 경우는 어떨까요??
    • 전체 조회하는 것을 확인할 수 있습니다..
    • 만약 데이터가 많을 경우 성능에 문제가 발생할 수 있으므로 limit, paging 조건이 필요할 수 있습니다..

 

 

 

 

 

 

Reference

  • 자바 ORM 표준 JPA 프로그래밍
  • QueryDSL

댓글