Skip to content

Commit

Permalink
Merge pull request #44 from K-Hackathon-Fledge/42-bug-fetch-join-pagi…
Browse files Browse the repository at this point in the history
…ng-error

BUG : Fetch join + Paging 에러 처리 -> QueryDSL 적용 및 Count 쿼리 추가
  • Loading branch information
JuseungL authored Aug 10, 2024
2 parents 40810e5 + 912a21f commit 5da6bab
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 21 deletions.
25 changes: 24 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.2'
Expand Down Expand Up @@ -50,11 +55,29 @@ dependencies {
implementation 'io.awspring.cloud:spring-cloud-starter-aws:2.4.4'
implementation 'io.awspring.cloud:spring-cloud-starter-aws-secrets-manager-config:2.4.4'


// swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

// queryDSL
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

tasks.named('test') {
useJUnitPlatform()
}


// QueryDsl
def querydslSrcDir = 'src/main/generated'

clean {
delete file(querydslSrcDir)
}

tasks.withType(JavaCompile) {
options.generatedSourceOutputDirectory = file(querydslSrcDir)
}

19 changes: 19 additions & 0 deletions src/main/java/com/fledge/fledgeserver/config/QueryDslConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.fledge.fledgeserver.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueryDslConfig {

@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import java.util.List;
import java.util.Optional;

public interface SupportPostRepository extends JpaRepository<SupportPost, Long> {
public interface SupportPostRepository extends JpaRepository<SupportPost, Long>, SupportPostRepositoryCustom {
@Query("SELECT s FROM SupportPost s " +
"JOIN FETCH s.member m " +
"LEFT JOIN FETCH s.images i " +
Expand All @@ -28,24 +28,24 @@ default SupportPost findSupportByIdOrThrow(Long supportId) {
.orElseThrow(() -> new CustomException(ErrorCode.SUPPORT_NOT_FOUND));
}

@Query("SELECT sp FROM SupportPost sp " +
"LEFT JOIN FETCH sp.images " +
"WHERE (:category IS NULL OR sp.supportCategory IN :category) " +
"AND (sp.title LIKE %:q% OR sp.reason LIKE %:q%) " +
"AND (:status IS NULL OR (" +
" (:status = 'ing' AND sp.supportPostStatus IN " +
" (com.fledge.fledgeserver.support.entity.SupportPostStatus.PENDING, " +
" com.fledge.fledgeserver.support.entity.SupportPostStatus.IN_PROGRESS)) " +
" OR " +
" (:status = 'end' AND sp.supportPostStatus IN " +
" (com.fledge.fledgeserver.support.entity.SupportPostStatus.COMPLETED, " +
" com.fledge.fledgeserver.support.entity.SupportPostStatus.TERMINATED))" +
")) " +
"ORDER BY sp.createdDate DESC")
Page<SupportPost> findByCategoryAndSearchAndSupportPostStatusWithImages(@Param("category") List<SupportCategory> category,
@Param("q") String q,
@Param("status") String status,
Pageable pageable);
// @Query("SELECT sp FROM SupportPost sp " +
// "LEFT JOIN sp.images " +
// "WHERE (:category IS NULL OR sp.supportCategory IN :category) " +
// "AND (sp.title LIKE %:q% OR sp.reason LIKE %:q%) " +
// "AND (:status IS NULL OR (" +
// " (:status = 'ing' AND sp.supportPostStatus IN " +
// " (com.fledge.fledgeserver.support.entity.SupportPostStatus.PENDING, " +
// " com.fledge.fledgeserver.support.entity.SupportPostStatus.IN_PROGRESS)) " +
// " OR " +
// " (:status = 'end' AND sp.supportPostStatus IN " +
// " (com.fledge.fledgeserver.support.entity.SupportPostStatus.COMPLETED, " +
// " com.fledge.fledgeserver.support.entity.SupportPostStatus.TERMINATED))" +
// ")) " +
// "ORDER BY sp.createdDate DESC")
// Page<SupportPost> findByCategoryAndSearchAndSupportPostStatusWithImages(@Param("category") List<SupportCategory> category,
// @Param("q") String q,
// @Param("status") String status,
// Pageable pageable);

@Query("SELECT sp FROM SupportPost sp " +
"WHERE FUNCTION('DATEDIFF', sp.expirationDate, CURRENT_DATE) <= 7 " +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.fledge.fledgeserver.support.repository;

import com.fledge.fledgeserver.support.entity.SupportCategory;
import com.fledge.fledgeserver.support.entity.SupportPost;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface SupportPostRepositoryCustom {
Page<SupportPost> findByCategoryAndSearchAndSupportPostStatusWithImages(
List<SupportCategory> category, String q, String status, Pageable pageable);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.fledge.fledgeserver.support.repository;

import com.fledge.fledgeserver.support.entity.QSupportPost;
import com.fledge.fledgeserver.support.entity.SupportCategory;
import com.fledge.fledgeserver.support.entity.SupportPost;
import com.fledge.fledgeserver.support.entity.SupportPostStatus;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import com.querydsl.core.types.dsl.BooleanExpression;

import java.util.List;

public class SupportPostRepositoryImpl extends QuerydslRepositorySupport implements SupportPostRepositoryCustom {

private final JPAQueryFactory queryFactory;

@Autowired
public SupportPostRepositoryImpl(JPAQueryFactory queryFactory) {
super(SupportPost.class);
this.queryFactory = queryFactory;
}

@Override
public Page<SupportPost> findByCategoryAndSearchAndSupportPostStatusWithImages(
List<SupportCategory> category, String q, String status, Pageable pageable) {

QSupportPost supportPost = QSupportPost.supportPost;

// 카운트 쿼리: 중복 없이 실제 SupportPost 엔티티 개수만 카운트
long total = queryFactory.selectFrom(supportPost)
.where(
categoryIsNullOrInCategory(supportPost, category),
titleOrReasonContains(supportPost, q),
statusIsNullOrMatches(supportPost, status)
).fetchCount();

List<SupportPost> results = queryFactory.selectFrom(supportPost)
.leftJoin(supportPost.images).fetchJoin()
.where(
categoryIsNullOrInCategory(supportPost, category),
titleOrReasonContains(supportPost, q),
statusIsNullOrMatches(supportPost, status)
)
.orderBy(supportPost.createdDate.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

return new PageImpl<>(results, pageable, total);
}

private BooleanExpression categoryIsNullOrInCategory(QSupportPost supportPost, List<SupportCategory> category) {
return category == null || category.isEmpty() ? null : supportPost.supportCategory.in(category);
}

private BooleanExpression titleOrReasonContains(QSupportPost supportPost, String q) {
if (q == null || q.isEmpty()) {
return null;
}
return supportPost.title.containsIgnoreCase(q)
.or(supportPost.reason.containsIgnoreCase(q));
}

private BooleanExpression statusIsNullOrMatches(QSupportPost supportPost, String status) {
if (status == null || status.isEmpty()) {
return null;
}
if ("ing".equals(status)) {
return supportPost.supportPostStatus.in(SupportPostStatus.PENDING, SupportPostStatus.IN_PROGRESS);
} else if ("end".equals(status)) {
return supportPost.supportPostStatus.in(SupportPostStatus.COMPLETED, SupportPostStatus.TERMINATED);
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ public PostTotalPagingResponse pagingSupportPost(int page, String q, List<String

RecordProgressGetResponse supportRecordProgress = new RecordProgressGetResponse(totalPrice, supportedPrice);
String imageUrl = supportPost.getImages().isEmpty() ? null : fileService.getDownloadPresignedUrl(supportPost.getImages().get(0).getImageUrl());
System.out.println("imageUrl = " + imageUrl);
return new PostPagingResponse(
supportPost.getId(),
supportPost.getTitle(),
Expand Down

0 comments on commit 5da6bab

Please sign in to comment.