From 93594ed52fb1c0cf085f08aa4800404adc6ba3d1 Mon Sep 17 00:00:00 2001 From: CodingLeeSeungHoon Date: Fri, 3 May 2024 13:07:28 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20category=20infra=20layer=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=BF=BC=EB=A6=AC=20QueryDSL=20=EA=B0=9C=EB=B0=9C,?= =?UTF-8?q?=20=EA=B8=B0=EC=A1=B4=20Repository=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#53)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dto/CategoryDetailViewData.java | 32 ++++ .../domain/dto/CategoryDetailViewDto.java | 15 ++ .../category/domain/dto/CategoryViewData.java | 24 +++ .../category/domain/dto/CategoryViewDto.java | 17 +++ .../repository/CategoryCustomRepository.java | 9 -- .../domain/repository/CategoryRepository.java | 5 +- .../repository/CategoryRepositoryCustom.java | 16 ++ .../infra/CategoryCustomRepositoryImpl.java | 16 -- .../infra/CategoryRepositoryImpl.java | 108 ++++++++++++++ .../CategoryCustomRepositoryImplTest.java | 139 ++++++++++++++++++ 10 files changed, 352 insertions(+), 29 deletions(-) create mode 100644 needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewData.java create mode 100644 needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewDto.java create mode 100644 needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewData.java create mode 100644 needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewDto.java delete mode 100644 needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryCustomRepository.java create mode 100644 needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepositoryCustom.java delete mode 100644 needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImpl.java create mode 100644 needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryRepositoryImpl.java create mode 100644 needeachother/src/test/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImplTest.java diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewData.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewData.java new file mode 100644 index 0000000..0c23546 --- /dev/null +++ b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewData.java @@ -0,0 +1,32 @@ +package com.neo.needeachother.category.domain.dto; + +import com.neo.needeachother.category.domain.ContentType; +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString(callSuper = true) +public class CategoryDetailViewData { + private final String categoryId; + private final String categoryTitle; + private final String categoryType; + private final boolean isHostWriteOnly; + private final boolean isCommentWriteAble; + private final boolean isUsingRateFilter; + private final int voteFilterRate; + private final long postInCategoryCount; + + public CategoryDetailViewData(String categoryId, String categoryTitle, String categoryType, + boolean isHostWriteOnly, boolean isCommentWriteAble, + boolean isUsingRateFilter, + int voteFilterRate, long postInCategoryCount) { + this.categoryId = categoryId; + this.categoryTitle = categoryTitle; + this.categoryType = ContentType.convertToContentType(categoryType).name(); + this.isHostWriteOnly = isHostWriteOnly; + this.isCommentWriteAble = isCommentWriteAble; + this.isUsingRateFilter = isUsingRateFilter; + this.voteFilterRate = voteFilterRate; + this.postInCategoryCount = postInCategoryCount; + } +} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewDto.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewDto.java new file mode 100644 index 0000000..edbc91d --- /dev/null +++ b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryDetailViewDto.java @@ -0,0 +1,15 @@ +package com.neo.needeachother.category.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +import java.util.List; + +@Getter +@ToString +@AllArgsConstructor +public class CategoryDetailViewDto { + private String starPageId; + private List viewData; +} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewData.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewData.java new file mode 100644 index 0000000..a9ec990 --- /dev/null +++ b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewData.java @@ -0,0 +1,24 @@ +package com.neo.needeachother.category.domain.dto; + +import com.neo.needeachother.category.domain.ContentType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString(callSuper = true) +public class CategoryViewData { + private String categoryId; + private String categoryTitle; + private String categoryType; + private long postCountInCategory; + + public CategoryViewData(String categoryId, String categoryTitle, String categoryType, long postCountInCategory){ + this.categoryId = categoryId; + this.categoryTitle = categoryTitle; + this.categoryType = ContentType.convertToContentType(categoryType).name(); + this.postCountInCategory = postCountInCategory; + } +} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewDto.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewDto.java new file mode 100644 index 0000000..ce1d6e3 --- /dev/null +++ b/needeachother/src/main/java/com/neo/needeachother/category/domain/dto/CategoryViewDto.java @@ -0,0 +1,17 @@ +package com.neo.needeachother.category.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +@Getter +@Setter +@ToString +@AllArgsConstructor +public class CategoryViewDto { + private String starPageId; + private List viewData; +} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryCustomRepository.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryCustomRepository.java deleted file mode 100644 index 3547476..0000000 --- a/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryCustomRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.neo.needeachother.category.domain.repository; - -import com.neo.needeachother.category.domain.CategoryId; -import com.neo.needeachother.category.domain.ContentType; -import org.springframework.stereotype.Repository; - -@Repository -public interface CategoryCustomRepository { -} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepository.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepository.java index af52230..310869e 100644 --- a/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepository.java +++ b/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepository.java @@ -2,15 +2,12 @@ import com.neo.needeachother.category.domain.Category; import com.neo.needeachother.category.domain.CategoryId; -import com.neo.needeachother.category.domain.ContentType; import com.neo.needeachother.starpage.domain.StarPageId; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; import java.util.Optional; -@Repository -public interface CategoryRepository extends CategoryCustomRepository, JpaRepository { +public interface CategoryRepository extends CategoryRepositoryCustom, JpaRepository { Optional findByCategoryIdAndStarPageId(CategoryId categoryId, StarPageId starPageId); } diff --git a/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepositoryCustom.java b/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepositoryCustom.java new file mode 100644 index 0000000..f8fdc4d --- /dev/null +++ b/needeachother/src/main/java/com/neo/needeachother/category/domain/repository/CategoryRepositoryCustom.java @@ -0,0 +1,16 @@ +package com.neo.needeachother.category.domain.repository; + +import com.neo.needeachother.category.domain.CategoryId; +import com.neo.needeachother.category.domain.ContentType; +import com.neo.needeachother.category.domain.dto.CategoryDetailViewDto; +import com.neo.needeachother.category.domain.dto.CategoryViewDto; +import com.neo.needeachother.starpage.domain.StarPageId; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +public interface CategoryRepositoryCustom { + Optional searchCategoryViewByStarPageId(StarPageId starPageId); + Optional searchCategoryDetailViewByStarPageId(StarPageId starPageId); +} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImpl.java b/needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImpl.java deleted file mode 100644 index d170270..0000000 --- a/needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImpl.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.neo.needeachother.category.infra; - -import com.neo.needeachother.category.domain.CategoryId; -import com.neo.needeachother.category.domain.ContentType; -import com.neo.needeachother.category.domain.repository.CategoryCustomRepository; -import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; - -import java.util.UUID; - -@RequiredArgsConstructor -public class CategoryCustomRepositoryImpl implements CategoryCustomRepository { - - private final JPAQueryFactory jpaQueryFactory; - -} diff --git a/needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryRepositoryImpl.java b/needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryRepositoryImpl.java new file mode 100644 index 0000000..fcc4508 --- /dev/null +++ b/needeachother/src/main/java/com/neo/needeachother/category/infra/CategoryRepositoryImpl.java @@ -0,0 +1,108 @@ +package com.neo.needeachother.category.infra; + +import com.neo.needeachother.category.domain.CategoryStatus; +import com.neo.needeachother.category.domain.dto.CategoryDetailViewData; +import com.neo.needeachother.category.domain.dto.CategoryDetailViewDto; +import com.neo.needeachother.category.domain.dto.CategoryViewData; +import com.neo.needeachother.category.domain.dto.CategoryViewDto; +import com.neo.needeachother.category.domain.repository.CategoryRepositoryCustom; +import com.neo.needeachother.common.exception.NEOUnexpectedException; +import com.neo.needeachother.starpage.domain.StarPageId; +import com.querydsl.core.group.GroupBy; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +import static com.neo.needeachother.category.domain.QCategory.category; +import static com.neo.needeachother.post.domain.QStarPagePost.starPagePost; + +@Repository +@RequiredArgsConstructor +public class CategoryRepositoryImpl implements CategoryRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public Optional searchCategoryViewByStarPageId(StarPageId starPageId) { + List queryResult = jpaQueryFactory + .select( + Expressions.asString(starPageId.getValue()).as("starPageId"), + category.categoryId.value, + category.categoryInformation.categoryTitle, + category.contentType.stringValue(), + starPagePost.count() + ) + .from(category) + .innerJoin(starPagePost).on(starPagePost.categoryId.eq(category.categoryId)) + .groupBy(category.categoryId) + .where( + categoryEqStarPageId(starPageId), + neCategoryStatusDeleted() + ) + .transform(GroupBy.groupBy(category.starPageId) + .list(Projections.constructor(CategoryViewDto.class, + Expressions.asString(starPageId.getValue()).as("starPageId"), + GroupBy.list( + Projections.constructor(CategoryViewData.class, + category.categoryId.value, + category.categoryInformation.categoryTitle, + category.contentType.stringValue(), + starPagePost.count()) + ) + ))); + + if (queryResult.size() > 1) { + throw new NEOUnexpectedException("정상적이지 않은 결과, searchCategoryViewByStarPageId"); + } + + return Optional.ofNullable(queryResult.isEmpty() ? null : queryResult.get(0)); + } + + @Override + public Optional searchCategoryDetailViewByStarPageId(StarPageId starPageId) { + List queryResult = jpaQueryFactory + .select(category, starPagePost.count()) + .from(category) + .innerJoin(starPagePost).on(starPagePost.categoryId.eq(category.categoryId)) + .groupBy(category.categoryId) + .where( + categoryEqStarPageId(starPageId), + neCategoryStatusDeleted() + ).transform(GroupBy.groupBy(category.starPageId) + .list( + Projections.constructor(CategoryDetailViewDto.class, + Expressions.asString(starPageId.getValue()).as("starPageId"), + GroupBy.list(Projections.constructor(CategoryDetailViewData.class, + category.categoryId.value, + category.categoryInformation.categoryTitle, + category.contentType.stringValue(), + category.restriction.onlyHostWriteContent, + category.restriction.isWriteAbleComment, + category.restriction.useCommentRatingFilter, + category.restriction.filteringRate, + starPagePost.count() + )) + ) + )); + + if (queryResult.size() > 1) { + throw new NEOUnexpectedException("정상적이지 않은 결과, searchCategoryDetailViewByStarPageId"); + } + + return Optional.ofNullable(queryResult.isEmpty() ? null : queryResult.get(0)); + } + + private BooleanExpression categoryEqStarPageId(StarPageId starPageId) { + return category.starPageId.eq(starPageId); + } + + private BooleanExpression neCategoryStatusDeleted() { + return category.categoryStatus.ne(CategoryStatus.DELETED); + } +} diff --git a/needeachother/src/test/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImplTest.java b/needeachother/src/test/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImplTest.java new file mode 100644 index 0000000..71107e6 --- /dev/null +++ b/needeachother/src/test/java/com/neo/needeachother/category/infra/CategoryCustomRepositoryImplTest.java @@ -0,0 +1,139 @@ +package com.neo.needeachother.category.infra; + +import com.neo.needeachother.category.domain.Category; +import com.neo.needeachother.category.domain.ContentRestriction; +import com.neo.needeachother.category.domain.dto.CategoryDetailViewDto; +import com.neo.needeachother.category.domain.dto.CategoryViewDto; +import com.neo.needeachother.category.domain.repository.CategoryRepository; +import com.neo.needeachother.post.domain.*; +import com.neo.needeachother.starpage.domain.SNSLine; +import com.neo.needeachother.starpage.domain.SNSType; +import com.neo.needeachother.starpage.domain.StarPage; +import com.neo.needeachother.starpage.domain.domainservice.CreateCategoryFromStarPageService; +import com.neo.needeachother.starpage.domain.domainservice.StarPageIdGenerateService; +import com.neo.needeachother.starpage.domain.repository.StarPageRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class CategoryCustomRepositoryImplTest { + + @Autowired + private StarPageRepository starPageRepository; + + @Autowired + private StarPageIdGenerateService idGenerateService; + + @Autowired + private CreateCategoryFromStarPageService createCategoryFromStarPageService; + + @Autowired + private CategoryRepository categoryRepository; + + @Autowired + private PostRepository postRepository; + + @Test + @Transactional + public void testForSearchCategoryViewByStarPageId(){ + StarPage dummyStarPage1 = starPageRepository.save(StarPage.create(idGenerateService.getNextId(), "박보영", "boyoung@naver.com", Set.of("ACTOR"), + List.of(SNSLine.of(SNSType.YOUTUBE, "boyoung.youtube.com")), "보영")); + + List savedCategory = categoryRepository.saveAll(List.of(dummyStarPage1.createCommonTypeCategory(createCategoryFromStarPageService, "공통형카테고리", + ContentRestriction.of(false, false, false, 0)), + dummyStarPage1.createAlbumTypeCategory(createCategoryFromStarPageService, "앨범형카테고리", + ContentRestriction.of(false, false, false, 0)), + dummyStarPage1.createGoldBalanceTypeCategory(createCategoryFromStarPageService, "황밸형카테고리", + ContentRestriction.of(false, false, false, 0)), + dummyStarPage1.createVoteTypeCategory(createCategoryFromStarPageService, "투표형카테고리", + ContentRestriction.of(false, false, false, 0)))); + + List savedPost = postRepository.saveAll(List.of( + savedCategory.get(0).writeCommonPost("글1번", Author.of("아무개1", "aaa@naver.com"), + List.of(CommonPostParagraph.ofTextParagraph("텍스트1"), + CommonPostParagraph.ofImageParagraph("이미지경로1"), + CommonPostParagraph.ofTextParagraph("텍스트2"), + CommonPostParagraph.ofImageParagraph("이미지경로2"))), + savedCategory.get(0).writeCommonPost("글2번", Author.of(dummyStarPage1.getInformation().getHost().getStarNickName(), + dummyStarPage1.getInformation().getHost().getEmail()), + List.of(CommonPostParagraph.ofTextParagraph("텍스트1"), + CommonPostParagraph.ofTextParagraph("텍스트2"), + CommonPostParagraph.ofImageParagraph("이미지경로2"))), + savedCategory.get(0).writeCommonPost("글3번", Author.of("아무개1", "aaa@naver.com"), + List.of(CommonPostParagraph.ofTextParagraph("텍스트1"), + CommonPostParagraph.ofImageParagraph("이미지경로1"), + CommonPostParagraph.ofTextParagraph("텍스트2"), + CommonPostParagraph.ofImageParagraph("이미지경로2"))), + savedCategory.get(1).writeAlbumPost("글4번", Author.of("아무개2", "bbb@naver.com"), + AlbumImage.of("이미지경로3")), + savedCategory.get(2).writeGoldBalancePost("글5번", Author.of("아무개3", "ccc@naver.com"), + "짜장면대짬뽕", "짜장면", "짬뽕"), + savedCategory.get(3).writeVotePost("글6번", Author.of("아무개4", "ddd@naver.com"), + "몇시", 3600, List.of(VoteItem.of("3시"), VoteItem.of("4시"), VoteItem.of("5시"))) + )); + + Optional maybeCategoryViewDto = + categoryRepository.searchCategoryViewByStarPageId(dummyStarPage1.getStarPageId()); + + System.out.println(maybeCategoryViewDto + .map(CategoryViewDto::toString) + .orElse("no data")); + + } + + @Test + @Transactional + public void testForSearchCategoryDetailViewByStarPageId(){ + StarPage dummyStarPage1 = starPageRepository.save(StarPage.create(idGenerateService.getNextId(), "박보영", "boyoung@naver.com", Set.of("ACTOR"), + List.of(SNSLine.of(SNSType.YOUTUBE, "boyoung.youtube.com")), "보영")); + + List savedCategory = categoryRepository.saveAll(List.of(dummyStarPage1.createCommonTypeCategory(createCategoryFromStarPageService, "공통형카테고리", + ContentRestriction.of(false, false, false, 0)), + dummyStarPage1.createAlbumTypeCategory(createCategoryFromStarPageService, "앨범형카테고리", + ContentRestriction.of(false, false, false, 0)), + dummyStarPage1.createGoldBalanceTypeCategory(createCategoryFromStarPageService, "황밸형카테고리", + ContentRestriction.of(false, false, false, 0)), + dummyStarPage1.createVoteTypeCategory(createCategoryFromStarPageService, "투표형카테고리", + ContentRestriction.of(false, false, false, 0)))); + + List savedPost = postRepository.saveAll(List.of( + savedCategory.get(0).writeCommonPost("글1번", Author.of("아무개1", "aaa@naver.com"), + List.of(CommonPostParagraph.ofTextParagraph("텍스트1"), + CommonPostParagraph.ofImageParagraph("이미지경로1"), + CommonPostParagraph.ofTextParagraph("텍스트2"), + CommonPostParagraph.ofImageParagraph("이미지경로2"))), + savedCategory.get(0).writeCommonPost("글2번", Author.of(dummyStarPage1.getInformation().getHost().getStarNickName(), + dummyStarPage1.getInformation().getHost().getEmail()), + List.of(CommonPostParagraph.ofTextParagraph("텍스트1"), + CommonPostParagraph.ofTextParagraph("텍스트2"), + CommonPostParagraph.ofImageParagraph("이미지경로2"))), + savedCategory.get(0).writeCommonPost("글3번", Author.of("아무개1", "aaa@naver.com"), + List.of(CommonPostParagraph.ofTextParagraph("텍스트1"), + CommonPostParagraph.ofImageParagraph("이미지경로1"), + CommonPostParagraph.ofTextParagraph("텍스트2"), + CommonPostParagraph.ofImageParagraph("이미지경로2"))), + savedCategory.get(1).writeAlbumPost("글4번", Author.of("아무개2", "bbb@naver.com"), + AlbumImage.of("이미지경로3")), + savedCategory.get(2).writeGoldBalancePost("글5번", Author.of("아무개3", "ccc@naver.com"), + "짜장면대짬뽕", "짜장면", "짬뽕"), + savedCategory.get(3).writeVotePost("글6번", Author.of("아무개4", "ddd@naver.com"), + "몇시", 3600, List.of(VoteItem.of("3시"), VoteItem.of("4시"), VoteItem.of("5시"))) + )); + + Optional maybeCategoryDetailViewDto = + categoryRepository.searchCategoryDetailViewByStarPageId(dummyStarPage1.getStarPageId()); + + System.out.println(maybeCategoryDetailViewDto + .map(CategoryDetailViewDto::toString) + .orElse("no data")); + } +} \ No newline at end of file