[Spring] Query DSL - 동적 쿼리

Kyungmin·2024년 4월 8일
0

Spring

목록 보기
10/39

동적 쿼리와 성능 최적화

1. Builder 사용

MemberTeamDto - 조회 최적화용 DTO 추가

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

참고: @QueryProjection 을 사용하면 해당 DTO가 Querydsl을 의존하게 된다. 이런 의존이 싫으면, 해당 에노테이션을 제거하고, Projection.bean(), fields(), constructor() 을 사용하면 된다.

회원 검색 조건

@Data
public class MemberSearchCondition {
//회원명, 팀명, 나이(ageGoe, ageLoe)
     private String username;
     private String teamName;
     private Integer ageGoe;	// 나이가 크거나 같음
     private Integer ageLoe;	// 나이가 작거나 같음
}

Builder를 사용한 예제

  • StringUtils.hasText(static 임포트 -> hasText)
//Builder 사용
//회원명, 팀명, 나이(ageGoe, ageLoe)
public List<MemberTeamDto> searchByBuilder(MemberSearchCondition condition) {
     BooleanBuilder builder = new BooleanBuilder();
     if (hasText(condition.getUsername())) {
         builder.and(member.username.eq(condition.getUsername()));
     }
     if (hasText(condition.getTeamName())) {
         builder.and(team.name.eq(condition.getTeamName()));
     }
     if (condition.getAgeGoe() != null) {
         builder.and(member.age.goe(condition.getAgeGoe()));
     }
     if (condition.getAgeLoe() != null) {
         builder.and(member.age.loe(condition.getAgeLoe()));
	}
     return queryFactory
             .select(new QMemberTeamDto(
                        member.id,
                        member.username,
                        member.age,
                        team.id,
                        team.name))
            .from(member)
            .leftJoin(member.team, team)
            .where(builder)
            .fetch();
}

2. Where절 파라미터 사용(권장)

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

  • 메서드 재사용이 가능(가장 큰 장점 - 권장하는 이유)
  • 가독성 증가
  • 조립(조합) 가능
//회원명, 팀명, 나이(ageGoe, ageLoe)
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 isEmpty(username) ? null : member.username.eq(username);
}
        
private BooleanExpression teamNameEq(String teamName) {
     return isEmpty(teamName) ? null : team.name.eq(teamName);
}
        
private BooleanExpression ageGoe(Integer ageGoe) {
     return ageGoe == null ? null : member.age.goe(ageGoe);
}
        
private BooleanExpression ageLoe(Integer ageLoe) {
     return ageLoe == null ? null : member.age.loe(ageLoe);
}
profile
Backend Developer

0개의 댓글

관련 채용 정보