Querydsl로 동적 검색 기능을 어떻게 적용할 수 있는지 설명해주세요.

권성현·2023년 3월 8일
0

면접 준비

목록 보기
23/30
post-custom-banner

build를 intellij로 위임해서 더빨리 빌드시키기

기본으로 실행하는게 자바에서 실행하는게 아니라 그래들에 실행을 위임하는게 디폴트 설정이기때문에 해당 탭으로가서 다음과 같이 수정합니다.

lombok 설정하기

plugin lombok을 다운 받으신 후에 해당 설정에 체크를 꼭 해주셔야 정상 동작합니다.

그래들파일 설정

    ext {
        queryDslVersion = "5.0.0"	// (1) querydsl의 버전
    }
}
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" //(2) querydsl 플러그인 추가
//querydsl 추가
   implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" //(3), (4) 라이브러리 dependency를 추가 및 버전 명시
   annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}"//(4)
   
task cleanGeneatedDir(type: Delete) { // 인텔리제이 annotation processor 가 생성한 Q클래스가 clean 태스크로 삭제되는 게 불편하다면 둘 중에 하나를 선택
   delete file('src/main/generated')
    //querydsl 추가 시작
def querydslDir = "$buildDir/generated/querydsl"	// (5) querydsl 에서 사용할 경로를 선언
querydsl {	// (6) querydsl 설정을 추가, JPA 사용 여부와 사용할 경로를 지정
    jpa = true
    querydslSourcesDir = querydslDir
}
sourceSets {	// (7)  build 시 사용할 sourceSet 추가
    main.java.srcDir querydslDir
}
configurations {	// (8) querydsl 이 compileClassPath 를 상속하도록 설정
    querydsl.extendsFrom compileClasspath
}
compileQuerydsl {	// (9) querydsl 컴파일시 사용할 옵션을 설정
    options.annotationProcessorPath = configurations.querydsl
}

Where절을 이용

public class BoardRepositoryImpl implements BoardCustomRepository{

    public final JPAQueryFactory queryFactory; // JPAQueryFactory 빈 주입

    public BoardCustomRepositoryImpl(EntityManager em) {
        this.queryFactory = new JPAQueryFactory(em);
    }

    @Override
    public List<Board> search(SearchCondition condition) { // 검색 쿼리
        return queryFactory
                .selectFrom(board)
                .where(isSearchable(condition.type, condition.content))
                .orderBy(board.writeTime.desc())
                .fetch();
    }

    ...
}

동적쿼리 만들기(BooleanExpression)

Querydsl에서 동적 쿼리 구현하는 방법
Querydsl에서는 동적쿼리를 해결하기 위해 BooleanBuilder와 Where 다중 파라미터를 사용하는 두 가지 방식이 있다.

둘다 같은 'Expression' 인터페이스를 구현하기 때문에 Where를 처리한다는 목적은 같지만, 생성하는 방법과 조건을 추가하는 방식에 차이가 있다.

BooleanExpression은 예시코드처럼 메소드를 따로 뺐기때문에, 가장 중요한 로직이 위에 오게되어 가독성이 높아지고 메소드 명을 통해 굳이 메소드의 내용을 보지 않더라도 쉽게 어떤 내용인지 파악이 가능하다.

또한 null을 반환하게 되면 Where절에서 조건은 무시되어 안전하고, BooleanExpression을 활용하면 아래처럼 and와 or같은 메소드들을 이용해 BooleanExpression들을 조합해 새로운 BooleanExpression을 만들 수 있어 재사용성이 높다.

@Test
public void 동적쿼리_WhereParam() throws Exception { String usernameParam = "member1";
Integer ageParam = 10;
      List<Member> result = searchMember2(usernameParam, ageParam);
      Assertions.assertThat(result.size()).isEqualTo(1);
  }
  private List<Member> searchMember2(String usernameCond, Integer ageCond) {
      return queryFactory
              .selectFrom(member)
              .where(usernameEq(usernameCond), ageEq(ageCond))
              .fetch();
  }
  private BooleanExpression usernameEq(String usernameCond) {
      return usernameCond != null ? member.username.eq(usernameCond) : null;
  }
  private BooleanExpression ageEq(Integer ageCond) {
      return ageCond != null ? member.age.eq(ageCond) : null;
}
profile
개발일지
post-custom-banner

0개의 댓글