diff --git a/api/src/main/java/com/sponus/sponusbe/domain/portfolio/controller/PortfolioController.java b/api/src/main/java/com/sponus/sponusbe/domain/portfolio/controller/PortfolioController.java index e6d35765..49eaf92f 100644 --- a/api/src/main/java/com/sponus/sponusbe/domain/portfolio/controller/PortfolioController.java +++ b/api/src/main/java/com/sponus/sponusbe/domain/portfolio/controller/PortfolioController.java @@ -4,9 +4,13 @@ import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -18,6 +22,7 @@ import com.sponus.coredomain.domain.common.ApiResponse; import com.sponus.coredomain.domain.organization.Organization; +import com.sponus.coredomain.domain.portfolio.repository.conditions.PortfolioSearchParam; import com.sponus.coreinfrasecurity.annotation.AuthOrganization; import com.sponus.sponusbe.domain.portfolio.dto.PortfolioCreateRequest; import com.sponus.sponusbe.domain.portfolio.dto.PortfolioCreateResponse; @@ -49,9 +54,10 @@ public ApiResponse createPortfolio( return ApiResponse.onSuccess(response); } - @GetMapping("/{portfolioId}") - public ApiResponse getPortfolio(@PathVariable Long portfolioId) { - PortfolioGetResponse response = portfolioService.getPortfolio(portfolioId); + @GetMapping + public ApiResponse> getPortfolios(@PageableDefault() Pageable pageable, @ModelAttribute + PortfolioSearchParam portfolioSearchParam) { + Page response = portfolioService.getPortfolios(portfolioSearchParam, pageable); return ApiResponse.onSuccess(response); } diff --git a/api/src/main/java/com/sponus/sponusbe/domain/portfolio/dto/PortfolioGetResponse.java b/api/src/main/java/com/sponus/sponusbe/domain/portfolio/dto/PortfolioGetResponse.java index d4b366eb..31ecaeba 100644 --- a/api/src/main/java/com/sponus/sponusbe/domain/portfolio/dto/PortfolioGetResponse.java +++ b/api/src/main/java/com/sponus/sponusbe/domain/portfolio/dto/PortfolioGetResponse.java @@ -1,9 +1,27 @@ package com.sponus.sponusbe.domain.portfolio.dto; +import java.time.LocalDate; import java.util.List; +import com.sponus.coredomain.domain.portfolio.Portfolio; + public record PortfolioGetResponse( Long portfolioId, + Long clubId, + LocalDate startDate, + LocalDate endDate, + String description, List portfolioImageGetResponses ) { + public static PortfolioGetResponse from(Portfolio portfolio, + List portfolioImageGetResponses) { + return new PortfolioGetResponse( + portfolio.getId(), + portfolio.getClub().getId(), + portfolio.getStartDate(), + portfolio.getEndDate(), + portfolio.getDescription(), + portfolioImageGetResponses + ); + } } diff --git a/api/src/main/java/com/sponus/sponusbe/domain/portfolio/service/PortfolioService.java b/api/src/main/java/com/sponus/sponusbe/domain/portfolio/service/PortfolioService.java index fb4cb3cf..86c6e386 100644 --- a/api/src/main/java/com/sponus/sponusbe/domain/portfolio/service/PortfolioService.java +++ b/api/src/main/java/com/sponus/sponusbe/domain/portfolio/service/PortfolioService.java @@ -8,6 +8,8 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -17,7 +19,9 @@ import com.sponus.coredomain.domain.organization.repository.ClubRepository; import com.sponus.coredomain.domain.portfolio.Portfolio; import com.sponus.coredomain.domain.portfolio.PortfolioImage; +import com.sponus.coredomain.domain.portfolio.repository.PortfolioCustomRepository; import com.sponus.coredomain.domain.portfolio.repository.PortfolioRepository; +import com.sponus.coredomain.domain.portfolio.repository.conditions.PortfolioSearchParam; import com.sponus.coreinfras3.S3Service; import com.sponus.sponusbe.domain.organization.exception.OrganizationException; import com.sponus.sponusbe.domain.portfolio.dto.PortfolioCreateRequest; @@ -37,6 +41,7 @@ @Service public class PortfolioService { private final PortfolioRepository portfolioRepository; + private final PortfolioCustomRepository portfolioCustomRepository; private final ClubRepository clubRepository; private final S3Service s3Service; @@ -94,15 +99,14 @@ public PortfolioCreateResponse createPortfolio( ); } - public PortfolioGetResponse getPortfolio(long portfolioId) { - Portfolio portfolio = portfolioRepository.findById(portfolioId) - .orElseThrow(() -> new PortfolioException(PORTFOLIO_NOT_FOUND)); - - List portfolioImageGetResponses = portfolio.getPortfolioImages().stream() - .map(image -> new PortfolioImageGetResponse(image.getId(), image.getUrl(), image.getOrder())) - .toList(); - - return new PortfolioGetResponse(portfolioId, portfolioImageGetResponses); + public Page getPortfolios(PortfolioSearchParam portfolioSearchParam, Pageable pageable) { + Page queryResult = portfolioCustomRepository.findAllByConditions(portfolioSearchParam, pageable); + return queryResult.map(portfolio -> { + List portfolioImageGetResponses = portfolio.getPortfolioImages().stream() + .map(image -> new PortfolioImageGetResponse(image.getId(), image.getUrl(), image.getOrder())) + .toList(); + return PortfolioGetResponse.from(portfolio, portfolioImageGetResponses); + }); } @Transactional diff --git a/core/core-domain/src/main/java/com/sponus/coredomain/config/QuerydslConfig.java b/core/core-domain/src/main/java/com/sponus/coredomain/config/QuerydslConfig.java new file mode 100644 index 00000000..39e64ce1 --- /dev/null +++ b/core/core-domain/src/main/java/com/sponus/coredomain/config/QuerydslConfig.java @@ -0,0 +1,20 @@ +package com.sponus.coredomain.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; + +@Configuration +public class QuerydslConfig { + @PersistenceContext + private EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(entityManager); + } +} diff --git a/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/Portfolio.java b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/Portfolio.java index fb5c0c9e..bea29f8f 100644 --- a/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/Portfolio.java +++ b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/Portfolio.java @@ -53,7 +53,7 @@ public class Portfolio { @Setter @Builder.Default - @OneToMany(cascade = {CascadeType.ALL}) + @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) private List portfolioImages = new ArrayList<>(); public void addPortfolioImage(PortfolioImage portfolioImage) { diff --git a/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/PortfolioCustomRepository.java b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/PortfolioCustomRepository.java new file mode 100644 index 00000000..1f78fa92 --- /dev/null +++ b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/PortfolioCustomRepository.java @@ -0,0 +1,11 @@ +package com.sponus.coredomain.domain.portfolio.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import com.sponus.coredomain.domain.portfolio.Portfolio; +import com.sponus.coredomain.domain.portfolio.repository.conditions.PortfolioSearchParam; + +public interface PortfolioCustomRepository { + Page findAllByConditions(PortfolioSearchParam portfolioSearchParam, Pageable pageable); +} diff --git a/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/PortfolioRepositoryImpl.java b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/PortfolioRepositoryImpl.java new file mode 100644 index 00000000..09e351b1 --- /dev/null +++ b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/PortfolioRepositoryImpl.java @@ -0,0 +1,52 @@ +package com.sponus.coredomain.domain.portfolio.repository; + +import static com.sponus.coredomain.domain.portfolio.QPortfolio.*; + +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.support.PageableExecutionUtils; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.sponus.coredomain.domain.portfolio.Portfolio; +import com.sponus.coredomain.domain.portfolio.repository.conditions.PortfolioSearchParam; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class PortfolioRepositoryImpl implements PortfolioCustomRepository { + private final JPAQueryFactory queryFactory; + + @Override + public Page findAllByConditions(PortfolioSearchParam portfolioSearchParam, + Pageable pageable) { + JPAQuery countQuery = queryFactory + .select(portfolio.count()) + .from(portfolio); + + List portfolios = queryFactory + .select(portfolio) + .from(portfolio) + .where( + isClubId(portfolioSearchParam.clubId()), + isPortfolioId(portfolioSearchParam.portfolioId()) + ) + .orderBy(portfolio.id.asc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + return PageableExecutionUtils.getPage(portfolios, pageable, countQuery::fetchOne); + } + + private BooleanExpression isClubId(Long clubId) { + return clubId != null ? portfolio.club.id.eq(clubId) : null; + } + + private BooleanExpression isPortfolioId(Long portfolioId) { + return portfolioId != null ? portfolio.club.id.eq(portfolioId) : null; + } +} diff --git a/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/conditions/PortfolioSearchParam.java b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/conditions/PortfolioSearchParam.java new file mode 100644 index 00000000..159c78f2 --- /dev/null +++ b/core/core-domain/src/main/java/com/sponus/coredomain/domain/portfolio/repository/conditions/PortfolioSearchParam.java @@ -0,0 +1,7 @@ +package com.sponus.coredomain.domain.portfolio.repository.conditions; + +public record PortfolioSearchParam( + Long portfolioId, + Long clubId +) { +}