[QueryDSL] join, paging, where, dto Qclass

2022. 12. 28. 00:17·JPA
728x90

사용 이유

jpa nativeQuery로 쿼리 조회를 하다가 다중 필터를 사용하게 되면서, where절을 유동적으로 사용하기위해 사용

 

// 설문조사 리스트 조회
@Query(value =
        "SELECT sc.content, s.* " +
        "FROM survey s left join survey_category sc on sc.sur_cat_id = s.category_id " +
        "WHERE 1=1 " +
        "and s.status = 'I' " +
        "and s.is_private = 'N' "
        "and s.category_id = :categoryId "
        , nativeQuery = true)
Page<Map<String,Object>> findByCategoryIdAndStatus(@Param("categoryId") int categoryId, Pageable pageable);

 

 


1. pom.xml에 dependency 추가

<!-- QueryDSL APT Config -->
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>${querydsl.version}</version>
    <scope>provided</scope>
</dependency>

<!-- QueryDSL JPA Config -->
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>${querydsl.version}</version>
</dependency>
<plugin>
    <groupId>com.mysema.maven</groupId>
    <artifactId>apt-maven-plugin</artifactId>
    <version>1.1.3</version>
    <executions>
        <execution>
            <goals>
                <goal>process</goal>
            </goals>
            <configuration>
                <outputDirectory>target/generated-sources/java</outputDirectory>
                <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
            </configuration>
        </execution>
    </executions>
</plugin>

 

2. Qclass 생성

pom.xml → Maven →  Generate Sources and Update Folders

 

3. SurveyRepositoryCustom.java

 public Page<SurveyDTO> findByRegIdAndCategoryIdAndStatusAndTitle(
            String title, String regId, Integer[] categoryId, SurveyStatus status, Pageable pageable) {

		//  CaseBuilder Expression 추가
        StringExpression caseStatusDeudateStr = new CaseBuilder()
                .when(qSurvey.dueDt.before(LocalDateTime.now())).then("마감")
                .when(qSurvey.dueDt.after(LocalDateTime.now())).then("배포").otherwise("");

		// qSurvey -> QSurveyDTO로 select
        List<SurveyDTO> list = queryFactory
                .select(new QSurveyDTO(
                         qSurvey.surId
                        ,qSurvey.title
                        ,qSurvey.description
                        ,qSurvey.surveyCategory.surCatId
                        ,qSurveyCategory.content.as("categoryContent")
                        ,qSurvey.version
                        ,qSurvey.status
                        ,qSurvey.dueDt
                        ,qSurvey.isLoginYn
                        ,qSurvey.isPrivateYn
                        ,qSurvey.isModifyYn
                        ,qSurvey.isAnnoyYn
                        ,qSurvey.regId
                        ,qSurvey.regDt
                        ,qSurvey.views
                        , new CaseBuilder()
                        .when(qSurvey.status.eq(SurveyStatus.valueOf("P"))).then("제작")
                        .when(qSurvey.status.eq(SurveyStatus.valueOf("I"))).then(caseStatusDeudateStr)
                        .otherwise("").as("statusName")
                        )
                )
                
                 // from 절
                .from(qSurvey)
                 // 테이블 조인
                .leftJoin(qSurveyCategory)
                .on(qSurvey.surveyCategory.surCatId.eq(qSurveyCategory.surCatId))
                // 조건절
               .where(
                    eqRegId(regId),
                    inCategoryId(categoryId),
                    likeTitle(title)
                )
                // 페이징
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .orderBy(qSurvey.regDt.desc())
                .fetch();


		// 페이징을 위해 전체 갯수 카운트
        Long count = queryFactory
                .select(qSurvey.count())
                .from(qSurvey)
                .leftJoin(qSurveyCategory)
                .on(qSurvey.surveyCategory.surCatId.eq(qSurveyCategory.surCatId))
                .where(
                        eqRegId(regId),
                        inCategoryId(categoryId),
                        likeTitle(title)
                )
                .fetchOne();


        return  new PageImpl<>(list, pageable, count);
    }

 

3-1. dto를 Qclass로 만드는 방법

생성자에 @QueryProjection 어노테이션 추가

@Data
//@NoArgsConstructor
//@AllArgsConstructor
@Builder
public class SurveyDTO {

    private int surId;
    private String title;
    private String description;
    private int categoryId;
    private String categoryContent;
    private int version;
    private SurveyStatus status;
    private LocalDateTime dueDt;
    private IsYn isLoginYn;
    private IsYn isPrivateYn;
    private IsYn isModifyYn;
    private IsYn isAnnoyYn;
    private String regId;
    private LocalDateTime regDt;
    private Integer views;
    private String statusName;

    @QueryProjection
    public SurveyDTO(int surId, String title, String description, int categoryId, String categoryContent, int version, SurveyStatus status, LocalDateTime dueDt, IsYn isLoginYn, IsYn isPrivateYn, IsYn isModifyYn, IsYn isAnnoyYn, String regId, LocalDateTime regDt, Integer views, String statusName) {
        this.surId = surId;
        this.title = title;
        this.description = description;
        this.categoryId = categoryId;
        this.categoryContent = categoryContent;
        this.version = version;
        this.status = status;
        this.dueDt = dueDt;
        this.isLoginYn = isLoginYn;
        this.isPrivateYn = isPrivateYn;
        this.isModifyYn = isModifyYn;
        this.isAnnoyYn = isAnnoyYn;
        this.regId = regId;
        this.regDt = regDt;
        this.views = views;
        this.statusName = statusName;
    }
}

 

3-2. where절 메서드

// where 절
// null로 리턴되는 경우 쿼리 where 절을 타지 않음

private BooleanExpression eqRegId(String regId) {
    if (StringUtils.isEmpty(regId)) {
        return null;
    }
    return qSurvey.regId.eq(regId);
}

private BooleanExpression inCategoryId(Integer[] cateId) {
    if (cateId == null || cateId.length <1) {
        return null;
    }
    return qSurvey.surveyCategory.surCatId.in(cateId);
}

private BooleanExpression eqStatus(SurveyStatus status) {
    if (StringUtils.isEmpty(String.valueOf(status))) {
        return null;
    }
    return qSurvey.status.eq(status);
}

private BooleanExpression likeTitle(String title) {
    if (title == null || StringUtils.isEmpty(title)) {
        return null;
    }
    return qSurvey.title.like("%"+title+"%");
}

 

 

 

728x90
'JPA' 카테고리의 다른 글
  • [JPA] @Lock 비관적 락, PESSIMISTIC_WRITE, 타임아웃, 트랜잭션
  • [JPA] 변경감지 Dirty Checking, @Transactional, @DynamicUpdate
  • [JPA] fetch join, EntityGraph, N+1, Pagination, firstResult/maxResults specified with collection fetch; applying in memory
Karla Ko
Karla Ko
𝘾𝙤𝙣𝙩𝙞𝙣𝙪𝙤𝙪𝙨𝙡𝙮 𝙄𝙢𝙥𝙧𝙤𝙫𝙞𝙣𝙜, 𝘾𝙤𝙣𝙨𝙩𝙖𝙣𝙩𝙡𝙮 𝘿𝙚𝙫𝙚𝙡𝙤𝙥𝙞𝙣𝙜 𝙔𝙚𝙨!
    250x250
  • Karla Ko
    karlaLog
    Karla Ko
  • 전체
    오늘
    어제
    • Total (467)
      • Spring (19)
      • JPA (4)
      • Cloud & Architecture (15)
        • Kubernetes (5)
        • Docker (3)
        • MSA (2)
        • GCP (1)
        • AWS (4)
      • Devops (1)
      • Message Queue (4)
        • Kafka (2)
        • RabbitMQ (2)
      • Git (4)
      • DB (4)
      • Java (9)
      • Python (4)
      • CS (11)
        • OS (8)
        • Network (2)
        • Algorithm (1)
      • Coding Test (392)
        • programmers (156)
        • Graph (43)
        • DP (37)
        • Search (31)
        • Tree (13)
        • Data Structure (26)
        • Combination (12)
        • Implement (18)
        • Geedy (23)
        • Sort (7)
        • Math (21)
        • geometry (2)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Algorithm
    다익스트라
    최대공약수
    스택
    자료구조
    DFS
    플로이드워셜
    그래프
    최소신장트리
    구현
    알고리즘
    구간합
    최단거리
    덱
    재귀
    큐
    힙
    정렬
    조합
    월간코드챌린지
    그리디
    동적계획법
    파이썬
    LIS
    프로그래머스
    BFS
    이분탐색
    트리
    DP
    백준
  • hELLO· Designed By정상우.v4.10.3
Karla Ko
[QueryDSL] join, paging, where, dto Qclass
상단으로

티스토리툴바