From 9666ec272fb88604a2d5bd1d158a43f475e84747 Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Fri, 13 Oct 2023 10:33:10 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor:=20=EC=83=81=ED=92=88=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EC=99=84=EC=84=B1=20API=20=EC=BB=A4=EC=84=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20=ED=8E=98=EC=9D=B4=EC=A7=95=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/application/ProductService.java | 32 ++++++++++++------- .../product/dto/SearchProductsResponse.java | 15 ++++----- .../persistence/ProductRepository.java | 14 ++++++-- .../presentation/ProductApiController.java | 5 ++- .../presentation/ProductController.java | 2 +- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/backend/src/main/java/com/funeat/product/application/ProductService.java b/backend/src/main/java/com/funeat/product/application/ProductService.java index 0301db183..1e1cbad9d 100644 --- a/backend/src/main/java/com/funeat/product/application/ProductService.java +++ b/backend/src/main/java/com/funeat/product/application/ProductService.java @@ -1,8 +1,5 @@ package com.funeat.product.application; -import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND; -import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND; - import com.funeat.common.dto.PageDto; import com.funeat.product.domain.Category; import com.funeat.product.domain.Product; @@ -30,16 +27,20 @@ import com.funeat.review.persistence.ReviewRepository; import com.funeat.review.persistence.ReviewTagRepository; import com.funeat.tag.domain.Tag; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND; +import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND; + @Service @Transactional(readOnly = true) public class ProductService { @@ -48,6 +49,7 @@ public class ProductService { private static final int TOP = 0; public static final String REVIEW_COUNT = "reviewCount"; private static final int RANKING_SIZE = 3; + private static final int PAGE_SIZE = 10; private final CategoryRepository categoryRepository; private final ProductRepository productRepository; @@ -115,15 +117,23 @@ public RankingProductsResponse getTop3Products() { return RankingProductsResponse.toResponse(rankingProductDtos); } - public SearchProductsResponse searchProducts(final String query, final Pageable pageable) { - final Page products = productRepository.findAllByNameContaining(query, pageable); + public SearchProductsResponse searchProducts(final String query, final Long lastId) { + final List products = findAllByNameContaining(query, lastId); - final PageDto pageDto = PageDto.toDto(products); + final boolean hasNext = products.size() > PAGE_SIZE; final List productDtos = products.stream() .map(SearchProductDto::toDto) .collect(Collectors.toList()); - return SearchProductsResponse.toResponse(pageDto, productDtos); + return SearchProductsResponse.toResponse(hasNext, productDtos); + } + + private List findAllByNameContaining(final String query, final Long lastId) { + final PageRequest size = PageRequest.of(0, PAGE_SIZE); + if (lastId == 0) { + return productRepository.findAllByNameContainingFirst(query, size); + } + return productRepository.findAllByNameContaining(query, lastId, size); } public SearchProductResultsResponse getSearchResults(final String query, final Pageable pageable) { diff --git a/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java b/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java index ccdeade5a..caf31ada3 100644 --- a/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java +++ b/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java @@ -1,24 +1,23 @@ package com.funeat.product.dto; -import com.funeat.common.dto.PageDto; import java.util.List; public class SearchProductsResponse { - private final PageDto page; + private final boolean hasNext; private final List products; - public SearchProductsResponse(final PageDto page, final List products) { - this.page = page; + public SearchProductsResponse(final boolean hasNext, final List products) { + this.hasNext = hasNext; this.products = products; } - public static SearchProductsResponse toResponse(final PageDto page, final List products) { - return new SearchProductsResponse(page, products); + public static SearchProductsResponse toResponse(final boolean hasNext, final List products) { + return new SearchProductsResponse(hasNext, products); } - public PageDto getPage() { - return page; + public boolean isHasNext() { + return hasNext; } public List getProducts() { diff --git a/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java b/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java index c3adc5c4b..9c4ea4a00 100644 --- a/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java +++ b/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java @@ -4,7 +4,6 @@ import com.funeat.product.domain.Product; import com.funeat.product.dto.ProductInCategoryDto; import com.funeat.product.dto.ProductReviewCountDto; -import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -12,6 +11,8 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; + public interface ProductRepository extends JpaRepository, JpaSpecificationExecutor { @Query(value = "SELECT new com.funeat.product.dto.ProductInCategoryDto(p.id, p.name, p.price, p.image, p.averageRating, COUNT(r)) " @@ -44,7 +45,16 @@ Page findAllByCategoryOrderByReviewCountDesc(@Param("categ + "ORDER BY " + "(CASE WHEN p.name LIKE CONCAT(:name, '%') THEN 1 ELSE 2 END), " + "p.id DESC") - Page findAllByNameContaining(@Param("name") final String name, final Pageable pageable); + List findAllByNameContainingFirst(@Param("name") final String name, final Pageable pageable); + + @Query("SELECT p FROM Product p " + + "JOIN Product p2 ON p2.id = :lastId " + + "WHERE p.name LIKE CONCAT('%', :name, '%') " + + "AND ((p2.name LIKE CONCAT(:name, '%') AND p.id < :lastId) OR (p.name NOT LIKE CONCAT(:name, '%') AND p.id < :lastId)) " + + "ORDER BY " + + "(CASE WHEN p.name LIKE CONCAT(:name, '%') THEN 1 ELSE 2 END), " + + "p.id DESC") + List findAllByNameContaining(@Param("name") final String name, final Long lastId, final Pageable pageable); @Query("SELECT new com.funeat.product.dto.ProductReviewCountDto(p, COUNT(r.id)) FROM Product p " + "LEFT JOIN Review r ON r.product.id = p.id " diff --git a/backend/src/main/java/com/funeat/product/presentation/ProductApiController.java b/backend/src/main/java/com/funeat/product/presentation/ProductApiController.java index f71a1a706..4fe3bdfe9 100644 --- a/backend/src/main/java/com/funeat/product/presentation/ProductApiController.java +++ b/backend/src/main/java/com/funeat/product/presentation/ProductApiController.java @@ -48,9 +48,8 @@ public ResponseEntity getRankingProducts() { @GetMapping("/search/products") public ResponseEntity searchProducts(@RequestParam final String query, - @PageableDefault final Pageable pageable) { - final PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()); - final SearchProductsResponse response = productService.searchProducts(query, pageRequest); + @RequestParam final Long lastId) { + final SearchProductsResponse response = productService.searchProducts(query, lastId); return ResponseEntity.ok(response); } diff --git a/backend/src/main/java/com/funeat/product/presentation/ProductController.java b/backend/src/main/java/com/funeat/product/presentation/ProductController.java index d7f9e653f..bbec1c93d 100644 --- a/backend/src/main/java/com/funeat/product/presentation/ProductController.java +++ b/backend/src/main/java/com/funeat/product/presentation/ProductController.java @@ -52,7 +52,7 @@ ResponseEntity getAllProductsInCategory( ) @GetMapping ResponseEntity searchProducts(@RequestParam final String query, - @PageableDefault final Pageable pageable); + @RequestParam final Long lastId); @Operation(summary = "상품 검색 결과 조회", description = "문자열을 받아 상품을 검색하고 검색 결과들을 조회한다.") @ApiResponse( From e8b84d12aecaf3139aba56d7c8d17c42bde1ed7d Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Fri, 13 Oct 2023 10:34:44 +0900 Subject: [PATCH 2/7] =?UTF-8?q?test:=20=EC=83=81=ED=92=88=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EC=99=84=EC=84=B1=20repository=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/ProductRepositoryTest.java | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java b/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java index 887958516..3cef04d8c 100644 --- a/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java +++ b/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java @@ -1,5 +1,14 @@ package com.funeat.product.persistence; +import com.funeat.common.RepositoryTest; +import com.funeat.product.dto.ProductInCategoryDto; +import com.funeat.product.dto.ProductReviewCountDto; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + import static com.funeat.fixture.CategoryFixture.카테고리_간편식사_생성; import static com.funeat.fixture.MemberFixture.멤버_멤버1_생성; import static com.funeat.fixture.MemberFixture.멤버_멤버2_생성; @@ -32,13 +41,6 @@ import static com.funeat.fixture.ReviewFixture.리뷰_이미지test5_평점5점_재구매O_생성; import static org.assertj.core.api.Assertions.assertThat; -import com.funeat.common.RepositoryTest; -import com.funeat.product.dto.ProductInCategoryDto; -import com.funeat.product.dto.ProductReviewCountDto; -import java.util.List; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - @SuppressWarnings("NonAsciiCharacters") class ProductRepositoryTest extends RepositoryTest { @@ -245,7 +247,7 @@ class findAllByAverageRatingGreaterThan3_성공_테스트 { } @Nested - class findAllByNameContaining_성공_테스트 { + class findAllByNameContainingFirst_성공_테스트 { @Test void 상품명에_검색어가_포함된_상품들을_조회한다() { @@ -257,12 +259,36 @@ class findAllByNameContaining_성공_테스트 { final var product2 = 상품_망고빙수_가격5000원_평점4점_생성(category); 복수_상품_저장(product1, product2); - final var page = 페이지요청_기본_생성(0, 10); + final var expected = List.of(product2, product1); + + // when + final var actual = productRepository.findAllByNameContainingFirst("망고", PageRequest.of(0, 2)); + + // then + assertThat(actual).usingRecursiveComparison() + .isEqualTo(expected); + } + } + + @Nested + class findAllByNameContaining_성공_테스트 { + + @Test + void 상품명에_검색어가_포함된_상품들을_조회한다() { + // given + final var category = 카테고리_간편식사_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_애플망고_가격3000원_평점5점_생성(category); + final var product2 = 상품_망고빙수_가격5000원_평점4점_생성(category); + final var product3 = 상품_망고빙수_가격5000원_평점4점_생성(category); + final var product4 = 상품_망고빙수_가격5000원_평점4점_생성(category); + 복수_상품_저장(product1, product2, product3, product4); final var expected = List.of(product2, product1); // when - final var actual = productRepository.findAllByNameContaining("망고", page).getContent(); + final var actual = productRepository.findAllByNameContaining("망고", 3L, PageRequest.of(0, 4)); // then assertThat(actual).usingRecursiveComparison() From 6d2186eb4a0bef5493058d67d42109b69d194c0a Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Fri, 13 Oct 2023 10:35:22 +0900 Subject: [PATCH 3/7] =?UTF-8?q?test:=20=EC=83=81=ED=92=88=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EC=99=84=EC=84=B1=20=EC=9D=B8=EC=88=98=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/ProductAcceptanceTest.java | 64 ++++++++----------- .../acceptance/product/ProductSteps.java | 9 ++- 2 files changed, 31 insertions(+), 42 deletions(-) diff --git a/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java index 03b2d9032..d9f6ddaf7 100644 --- a/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java @@ -1,5 +1,23 @@ package com.funeat.acceptance.product; +import com.funeat.acceptance.common.AcceptanceTest; +import com.funeat.product.domain.Category; +import com.funeat.product.dto.ProductInCategoryDto; +import com.funeat.product.dto.ProductResponse; +import com.funeat.product.dto.RankingProductDto; +import com.funeat.product.dto.SearchProductDto; +import com.funeat.product.dto.SearchProductResultDto; +import com.funeat.product.dto.SearchProductsResponse; +import com.funeat.recipe.dto.RecipeDto; +import com.funeat.tag.dto.TagDto; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; + import static com.funeat.acceptance.auth.LoginSteps.로그인_쿠키_획득; import static com.funeat.acceptance.common.CommonSteps.STATUS_CODE를_검증한다; import static com.funeat.acceptance.common.CommonSteps.사진_명세_요청; @@ -90,22 +108,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; -import com.funeat.acceptance.common.AcceptanceTest; -import com.funeat.product.domain.Category; -import com.funeat.product.dto.ProductInCategoryDto; -import com.funeat.product.dto.ProductResponse; -import com.funeat.product.dto.RankingProductDto; -import com.funeat.product.dto.SearchProductDto; -import com.funeat.product.dto.SearchProductResultDto; -import com.funeat.recipe.dto.RecipeDto; -import com.funeat.tag.dto.TagDto; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; -import java.util.Collections; -import java.util.List; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - @SuppressWarnings("NonAsciiCharacters") class ProductAcceptanceTest extends AcceptanceTest { @@ -433,14 +435,11 @@ class searchProducts_성공_테스트 { final var 상품1 = 단일_상품_저장(상품_애플망고_가격3000원_평점5점_생성(카테고리)); final var 상품2 = 단일_상품_저장(상품_망고빙수_가격5000원_평점4점_생성(카테고리)); - final var 예상_응답_페이지 = 응답_페이지_생성(총_데이터_개수(2L), 총_페이지(1L), 첫페이지O, 마지막페이지O, FIRST_PAGE, PAGE_SIZE); - // when - final var 응답 = 상품_자동_완성_검색_요청("망고", FIRST_PAGE); + final var 응답 = 상품_자동_완성_검색_요청("망고", 0L); // then STATUS_CODE를_검증한다(응답, 정상_처리); - 페이지를_검증한다(응답, 예상_응답_페이지); 상품_자동_완성_검색_결과를_검증한다(응답, List.of(상품2, 상품1)); } @@ -451,14 +450,11 @@ class searchProducts_성공_테스트 { 단일_카테고리_저장(카테고리); 반복_애플망고_상품_저장(2, 카테고리); - final var 예상_응답_페이지 = 응답_페이지_생성(총_데이터_개수(0L), 총_페이지(0L), 첫페이지O, 마지막페이지O, FIRST_PAGE, PAGE_SIZE); - // when - final var 응답 = 상품_자동_완성_검색_요청("김밥", FIRST_PAGE); + final var 응답 = 상품_자동_완성_검색_요청("김밥", 0L); // then STATUS_CODE를_검증한다(응답, 정상_처리); - 페이지를_검증한다(응답, 예상_응답_페이지); 상품_자동_완성_검색_결과를_검증한다(응답, Collections.emptyList()); } @@ -468,21 +464,18 @@ class searchProducts_성공_테스트 { final var 카테고리 = 카테고리_간편식사_생성(); 단일_카테고리_저장(카테고리); 단일_상품_저장(상품_망고빙수_가격5000원_평점4점_생성(카테고리)); - 반복_애플망고_상품_저장(10, 카테고리); - - final var 예상_응답_페이지1 = 응답_페이지_생성(총_데이터_개수(11L), 총_페이지(2L), 첫페이지O, 마지막페이지X, FIRST_PAGE, PAGE_SIZE); - final var 예상_응답_페이지2 = 응답_페이지_생성(총_데이터_개수(11L), 총_페이지(2L), 첫페이지X, 마지막페이지O, SECOND_PAGE, PAGE_SIZE); + 반복_애플망고_상품_저장(15, 카테고리); // when - final var 응답1 = 상품_자동_완성_검색_요청("망고", FIRST_PAGE); - final var 응답2 = 상품_자동_완성_검색_요청("망고", SECOND_PAGE); + final var 응답1 = 상품_자동_완성_검색_요청("망고", 0L); + + final var result = 응답1.as(SearchProductsResponse.class).getProducts(); + final var lastId = result.get(result.size() - 1).getId(); + final var 응답2 = 상품_자동_완성_검색_요청("망고", lastId); // then STATUS_CODE를_검증한다(응답1, 정상_처리); - 페이지를_검증한다(응답1, 예상_응답_페이지1); - STATUS_CODE를_검증한다(응답2, 정상_처리); - 페이지를_검증한다(응답2, 예상_응답_페이지2); 결과값이_이전_요청_결과값에_중복되는지_검증(응답1, 응답2); } @@ -496,14 +489,11 @@ class searchProducts_성공_테스트 { 반복_애플망고_상품_저장(9, 카테고리); 단일_상품_저장(상품_망고빙수_가격5000원_평점4점_생성(카테고리)); - final var 예상_응답_페이지 = 응답_페이지_생성(총_데이터_개수(11L), 총_페이지(2L), 첫페이지O, 마지막페이지X, FIRST_PAGE, PAGE_SIZE); - // when - final var 응답 = 상품_자동_완성_검색_요청("망고", FIRST_PAGE); + final var 응답 = 상품_자동_완성_검색_요청("망고", 0L); // then STATUS_CODE를_검증한다(응답, 정상_처리); - 페이지를_검증한다(응답, 예상_응답_페이지); 상품_자동_완성_검색_결과를_검증한다(응답, List.of(상품11, 상품1, 상품10, 상품9, 상품8, 상품7, 상품6, 상품5, 상품4, 상품3)); } } diff --git a/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java b/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java index 8092bc187..59b00fb91 100644 --- a/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java +++ b/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java @@ -1,11 +1,10 @@ package com.funeat.acceptance.product; -import static io.restassured.RestAssured.given; - - import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import static io.restassured.RestAssured.given; + @SuppressWarnings("NonAsciiCharacters") public class ProductSteps { @@ -36,10 +35,10 @@ public class ProductSteps { .extract(); } - public static ExtractableResponse 상품_자동_완성_검색_요청(final String query, final Long page) { + public static ExtractableResponse 상품_자동_완성_검색_요청(final String query, final Long lastId) { return given() .queryParam("query", query) - .queryParam("page", page) + .queryParam("lastId", lastId) .when() .get("/api/search/products") .then() From 0d35f0423da30c7270204b32490997bc6fe3c63c Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Thu, 19 Oct 2023 10:45:19 +0900 Subject: [PATCH 4/7] =?UTF-8?q?style:=20import=20=EC=A0=95=EB=A0=AC=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/application/ProductService.java | 15 ++++---- .../persistence/ProductRepository.java | 3 +- .../product/ProductAcceptanceTest.java | 35 +++++++++---------- .../acceptance/product/ProductSteps.java | 4 +-- .../persistence/ProductRepositoryTest.java | 17 +++++---- 5 files changed, 35 insertions(+), 39 deletions(-) diff --git a/backend/src/main/java/com/funeat/product/application/ProductService.java b/backend/src/main/java/com/funeat/product/application/ProductService.java index 1e1cbad9d..af095b500 100644 --- a/backend/src/main/java/com/funeat/product/application/ProductService.java +++ b/backend/src/main/java/com/funeat/product/application/ProductService.java @@ -1,5 +1,8 @@ package com.funeat.product.application; +import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND; +import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND; + import com.funeat.common.dto.PageDto; import com.funeat.product.domain.Category; import com.funeat.product.domain.Product; @@ -27,20 +30,16 @@ import com.funeat.review.persistence.ReviewRepository; import com.funeat.review.persistence.ReviewTagRepository; import com.funeat.tag.domain.Tag; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND; -import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND; - @Service @Transactional(readOnly = true) public class ProductService { diff --git a/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java b/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java index 9c4ea4a00..8a04bdb1f 100644 --- a/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java +++ b/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java @@ -4,6 +4,7 @@ import com.funeat.product.domain.Product; import com.funeat.product.dto.ProductInCategoryDto; import com.funeat.product.dto.ProductReviewCountDto; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -11,8 +12,6 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import java.util.List; - public interface ProductRepository extends JpaRepository, JpaSpecificationExecutor { @Query(value = "SELECT new com.funeat.product.dto.ProductInCategoryDto(p.id, p.name, p.price, p.image, p.averageRating, COUNT(r)) " diff --git a/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java index d9f6ddaf7..c2c43b812 100644 --- a/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java @@ -1,23 +1,5 @@ package com.funeat.acceptance.product; -import com.funeat.acceptance.common.AcceptanceTest; -import com.funeat.product.domain.Category; -import com.funeat.product.dto.ProductInCategoryDto; -import com.funeat.product.dto.ProductResponse; -import com.funeat.product.dto.RankingProductDto; -import com.funeat.product.dto.SearchProductDto; -import com.funeat.product.dto.SearchProductResultDto; -import com.funeat.product.dto.SearchProductsResponse; -import com.funeat.recipe.dto.RecipeDto; -import com.funeat.tag.dto.TagDto; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.List; - import static com.funeat.acceptance.auth.LoginSteps.로그인_쿠키_획득; import static com.funeat.acceptance.common.CommonSteps.STATUS_CODE를_검증한다; import static com.funeat.acceptance.common.CommonSteps.사진_명세_요청; @@ -108,6 +90,23 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; +import com.funeat.acceptance.common.AcceptanceTest; +import com.funeat.product.domain.Category; +import com.funeat.product.dto.ProductInCategoryDto; +import com.funeat.product.dto.ProductResponse; +import com.funeat.product.dto.RankingProductDto; +import com.funeat.product.dto.SearchProductDto; +import com.funeat.product.dto.SearchProductResultDto; +import com.funeat.product.dto.SearchProductsResponse; +import com.funeat.recipe.dto.RecipeDto; +import com.funeat.tag.dto.TagDto; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + @SuppressWarnings("NonAsciiCharacters") class ProductAcceptanceTest extends AcceptanceTest { diff --git a/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java b/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java index 59b00fb91..a24440dc1 100644 --- a/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java +++ b/backend/src/test/java/com/funeat/acceptance/product/ProductSteps.java @@ -1,10 +1,10 @@ package com.funeat.acceptance.product; +import static io.restassured.RestAssured.given; + import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import static io.restassured.RestAssured.given; - @SuppressWarnings("NonAsciiCharacters") public class ProductSteps { diff --git a/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java b/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java index 3cef04d8c..dbcf77ace 100644 --- a/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java +++ b/backend/src/test/java/com/funeat/product/persistence/ProductRepositoryTest.java @@ -1,14 +1,5 @@ package com.funeat.product.persistence; -import com.funeat.common.RepositoryTest; -import com.funeat.product.dto.ProductInCategoryDto; -import com.funeat.product.dto.ProductReviewCountDto; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.data.domain.PageRequest; - -import java.util.List; - import static com.funeat.fixture.CategoryFixture.카테고리_간편식사_생성; import static com.funeat.fixture.MemberFixture.멤버_멤버1_생성; import static com.funeat.fixture.MemberFixture.멤버_멤버2_생성; @@ -41,6 +32,14 @@ import static com.funeat.fixture.ReviewFixture.리뷰_이미지test5_평점5점_재구매O_생성; import static org.assertj.core.api.Assertions.assertThat; +import com.funeat.common.RepositoryTest; +import com.funeat.product.dto.ProductInCategoryDto; +import com.funeat.product.dto.ProductReviewCountDto; +import java.util.List; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.PageRequest; + @SuppressWarnings("NonAsciiCharacters") class ProductRepositoryTest extends RepositoryTest { From e2a926530940c39404082564ed0112ed03f64c37 Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Thu, 19 Oct 2023 10:49:07 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refactor:=20SearchProductsResponse=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20private=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/funeat/product/dto/SearchProductsResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java b/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java index caf31ada3..098c8e506 100644 --- a/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java +++ b/backend/src/main/java/com/funeat/product/dto/SearchProductsResponse.java @@ -7,7 +7,7 @@ public class SearchProductsResponse { private final boolean hasNext; private final List products; - public SearchProductsResponse(final boolean hasNext, final List products) { + private SearchProductsResponse(final boolean hasNext, final List products) { this.hasNext = hasNext; this.products = products; } From 0de0e26d6d8b73d33c774781a0574ce512a268e1 Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Thu, 19 Oct 2023 10:50:33 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20PageRequest=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/funeat/product/application/ProductService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/funeat/product/application/ProductService.java b/backend/src/main/java/com/funeat/product/application/ProductService.java index af095b500..5aa2b9986 100644 --- a/backend/src/main/java/com/funeat/product/application/ProductService.java +++ b/backend/src/main/java/com/funeat/product/application/ProductService.java @@ -128,7 +128,7 @@ public SearchProductsResponse searchProducts(final String query, final Long last } private List findAllByNameContaining(final String query, final Long lastId) { - final PageRequest size = PageRequest.of(0, PAGE_SIZE); + final PageRequest size = PageRequest.ofSize(PAGE_SIZE); if (lastId == 0) { return productRepository.findAllByNameContainingFirst(query, size); } From 360771acde0ad5fa1a9e598565334ffb6be55d02 Mon Sep 17 00:00:00 2001 From: Go-Jaecheol Date: Thu, 19 Oct 2023 11:29:24 +0900 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=EC=83=81=ED=92=88=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EC=99=84=EC=84=B1=20=EC=A1=B0=ED=9A=8C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../funeat/product/persistence/ProductRepository.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java b/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java index 8a04bdb1f..83a53f483 100644 --- a/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java +++ b/backend/src/main/java/com/funeat/product/persistence/ProductRepository.java @@ -47,12 +47,12 @@ Page findAllByCategoryOrderByReviewCountDesc(@Param("categ List findAllByNameContainingFirst(@Param("name") final String name, final Pageable pageable); @Query("SELECT p FROM Product p " - + "JOIN Product p2 ON p2.id = :lastId " + + "JOIN Product last ON last.id = :lastId " + "WHERE p.name LIKE CONCAT('%', :name, '%') " - + "AND ((p2.name LIKE CONCAT(:name, '%') AND p.id < :lastId) OR (p.name NOT LIKE CONCAT(:name, '%') AND p.id < :lastId)) " - + "ORDER BY " - + "(CASE WHEN p.name LIKE CONCAT(:name, '%') THEN 1 ELSE 2 END), " - + "p.id DESC") + + "AND (last.name LIKE CONCAT(:name, '%') " + + "AND ((p.name LIKE CONCAT(:name, '%') AND p.id < :lastId) OR (p.name NOT LIKE CONCAT(:name, '%'))) " + + "OR (p.name NOT LIKE CONCAT(:name, '%') AND p.id < :lastId)) " + + "ORDER BY (CASE WHEN p.name LIKE CONCAT(:name, '%') THEN 1 ELSE 2 END), p.id DESC") List findAllByNameContaining(@Param("name") final String name, final Long lastId, final Pageable pageable); @Query("SELECT new com.funeat.product.dto.ProductReviewCountDto(p, COUNT(r.id)) FROM Product p "