Skip to content

Commit

Permalink
refactor: 정렬만 하는 서비스 클래스 분리, Tag까지 가져올 수 있도록 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
70825 committed Oct 16, 2023
1 parent bbd289a commit e72b3d0
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@
import com.funeat.review.dto.SortingReviewDto;
import com.funeat.review.dto.SortingReviewRequest;
import com.funeat.review.dto.SortingReviewsResponse;
import com.funeat.review.dto.TestSortingReviewDto;
import com.funeat.review.exception.ReviewException.ReviewNotFoundException;
import com.funeat.review.persistence.ReviewRepository;
import com.funeat.review.persistence.ReviewTagRepository;
import com.funeat.review.specification.SortingReviewSpecification;
import com.funeat.tag.domain.Tag;
import com.funeat.tag.persistence.TagRepository;
import java.util.List;
Expand All @@ -42,7 +40,6 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
Expand All @@ -54,9 +51,7 @@ public class ReviewService {
private static final int START = 0;
private static final int ONE = 1;
private static final String EMPTY_URL = "";
private static final int PAGE_SIZE = 10;
private static final boolean EXIST_NEXT_DATA = true;
private static final boolean NOT_EXIST_NEXT_DATA = false;
private static final int REVIEW_PAGE_SIZE = 10;

private final ReviewRepository reviewRepository;
private final TagRepository tagRepository;
Expand All @@ -65,19 +60,21 @@ public class ReviewService {
private final ProductRepository productRepository;
private final ReviewFavoriteRepository reviewFavoriteRepository;
private final ImageUploader imageUploader;
private final SortingReviewService sortingReviewService;

public ReviewService(final ReviewRepository reviewRepository, final TagRepository tagRepository,
final ReviewTagRepository reviewTagRepository, final MemberRepository memberRepository,
final ProductRepository productRepository,
final ReviewFavoriteRepository reviewFavoriteRepository,
final ImageUploader imageUploader) {
final ImageUploader imageUploader, final SortingReviewService sortingReviewService) {
this.reviewRepository = reviewRepository;
this.tagRepository = tagRepository;
this.reviewTagRepository = reviewTagRepository;
this.memberRepository = memberRepository;
this.productRepository = productRepository;
this.reviewFavoriteRepository = reviewFavoriteRepository;
this.imageUploader = imageUploader;
this.sortingReviewService = sortingReviewService;
}

@Transactional
Expand Down Expand Up @@ -148,40 +145,29 @@ public void updateProductImage(final Long reviewId) {

public SortingReviewsResponse sortingReviews(final Long productId, final Long memberId,
final SortingReviewRequest request) {
final Member member = memberRepository.findById(memberId)
final Member findMember = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId));
final Product product = productRepository.findById(productId)
final Product findProduct = productRepository.findById(productId)
.orElseThrow(() -> new ProductNotFoundException(PRODUCT_NOT_FOUND, productId));

final List<SortingReviewDto> sortingReviews = getSortingReviews(member, product, request);
if (sortingReviews.size() > PAGE_SIZE) {
final List<SortingReviewDto> resizeSortingReviews = sortingReviews.subList(START, PAGE_SIZE);
return SortingReviewsResponse.toResponse(resizeSortingReviews, EXIST_NEXT_DATA);
}
return SortingReviewsResponse.toResponse(sortingReviews, NOT_EXIST_NEXT_DATA);
}
final List<SortingReviewDto> sortingReviews = sortingReviewService.getSortingReviews(findMember, findProduct, request);
final int resultSize = getResultSize(sortingReviews);

private List<SortingReviewDto> getSortingReviews(final Member member, final Product product,
final SortingReviewRequest request) {
final Long lastReviewId = request.getLastReviewId();
final String sortOption = request.getSort();
final List<SortingReviewDto> resizeSortingReviews = sortingReviews.subList(START, resultSize);
final Boolean hasNext = hasNextPage(sortingReviews);

final Specification<Review> specification = getSortingSpecification(product, sortOption, lastReviewId);
final List<TestSortingReviewDto> sortingReviewsTest = reviewRepository.getSortingReview(member, specification,
sortOption);
return sortingReviewsTest.stream()
.map(SortingReviewDto::toDto)
.collect(Collectors.toList());
return SortingReviewsResponse.toResponse(resizeSortingReviews, hasNext);
}

private Specification<Review> getSortingSpecification(final Product product, final String sortOption,
final Long lastReviewId) {
if (lastReviewId == START) {
return SortingReviewSpecification.sortingFirstPageBy(product);
private int getResultSize(final List<SortingReviewDto> sortingReviews) {
if (sortingReviews.size() <= REVIEW_PAGE_SIZE) {
return sortingReviews.size();
}
final Review lastReview = reviewRepository.findById(lastReviewId)
.orElseThrow(() -> new ReviewNotFoundException(REVIEW_NOT_FOUND, lastReviewId));
return SortingReviewSpecification.sortingBy(product, sortOption, lastReview);
return REVIEW_PAGE_SIZE;
}

private Boolean hasNextPage(final List<SortingReviewDto> sortingReviews) {
return sortingReviews.size() > REVIEW_PAGE_SIZE;
}

public RankingReviewsResponse getTopReviews() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.funeat.review.application;

import static com.funeat.review.exception.ReviewErrorCode.REVIEW_NOT_FOUND;

import com.funeat.member.domain.Member;
import com.funeat.product.domain.Product;
import com.funeat.review.domain.Review;
import com.funeat.review.dto.SortingReviewDto;
import com.funeat.review.dto.SortingReviewDtoWithoutTag;
import com.funeat.review.dto.SortingReviewRequest;
import com.funeat.review.exception.ReviewException.ReviewNotFoundException;
import com.funeat.review.persistence.ReviewRepository;
import com.funeat.review.specification.SortingReviewSpecification;
import com.funeat.tag.persistence.TagRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
public class SortingReviewService {

private static final int FIRST_PAGE = 0;

private final ReviewRepository reviewRepository;
private final TagRepository tagRepository;

public SortingReviewService(final ReviewRepository reviewRepository, final TagRepository tagRepository) {
this.reviewRepository = reviewRepository;
this.tagRepository = tagRepository;
}

public List<SortingReviewDto> getSortingReviews(final Member member, final Product product,
final SortingReviewRequest request) {
final Long lastReviewId = request.getLastReviewId();
final String sortOption = request.getSort();

final Specification<Review> specification = getSortingSpecification(product, sortOption, lastReviewId);
final List<SortingReviewDtoWithoutTag> sortingReviewDtoWithoutTags = reviewRepository.getSortingReview(member,
specification, sortOption);
final List<SortingReviewDto> sortingReviewDtos = addTagsToSortingReviews(sortingReviewDtoWithoutTags);

return sortingReviewDtos;
}

private List<SortingReviewDto> addTagsToSortingReviews(
final List<SortingReviewDtoWithoutTag> sortingReviewDtoWithoutTags) {
return sortingReviewDtoWithoutTags.stream()
.map(reviewDto -> SortingReviewDto.toDto(reviewDto,
tagRepository.findTagsByReviewId(reviewDto.getId())))
.collect(Collectors.toList());
}

private Specification<Review> getSortingSpecification(final Product product, final String sortOption,
final Long lastReviewId) {
if (lastReviewId == FIRST_PAGE) {
return SortingReviewSpecification.sortingFirstPageBy(product);
}

final Review lastReview = reviewRepository.findById(lastReviewId)
.orElseThrow(() -> new ReviewNotFoundException(REVIEW_NOT_FOUND, lastReviewId));

return SortingReviewSpecification.sortingBy(product, sortOption, lastReview);
}
}
57 changes: 15 additions & 42 deletions backend/src/main/java/com/funeat/review/dto/SortingReviewDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public class SortingReviewDto {
Expand Down Expand Up @@ -46,22 +45,24 @@ public SortingReviewDto(final Long id, final String userName, final String profi
this.createdAt = createdAt;
}

public static SortingReviewDto toDto(final TestSortingReviewDto dto) {
final Boolean isFavorite = checkingFavorite(dto.getFavorite());
public static SortingReviewDto toDto(final SortingReviewDtoWithoutTag sortingReviewDto, final List<Tag> tags) {
final List<TagDto> tagDtos = tags.stream()
.map(TagDto::toDto)
.collect(Collectors.toList());
final Boolean isFavorite = checkingFavorite(sortingReviewDto.getFavorite());

return new SortingReviewDto(
dto.getId(),
dto.getUserName(),
dto.getProfileImage(),
dto.getImage(),
dto.getRating(),
Collections.emptyList(),
dto.getContent(),
dto.getRebuy(),
dto.getFavoriteCount(),
sortingReviewDto.getId(),
sortingReviewDto.getUserName(),
sortingReviewDto.getProfileImage(),
sortingReviewDto.getImage(),
sortingReviewDto.getRating(),
tagDtos,
sortingReviewDto.getContent(),
sortingReviewDto.getRebuy(),
sortingReviewDto.getFavoriteCount(),
isFavorite,
dto.getCreatedAt()
);
sortingReviewDto.getCreatedAt());
}

private static Boolean checkingFavorite(final Boolean favorite) {
Expand All @@ -71,34 +72,6 @@ private static Boolean checkingFavorite(final Boolean favorite) {
return Boolean.TRUE;
}

public static SortingReviewDto toDto(final SortingReviewDto sortingReviewDto, final List<Tag> tags) {
final List<TagDto> tagDtos = tags.stream()
.map(TagDto::toDto)
.collect(Collectors.toList());

return new SortingReviewDto(sortingReviewDto.getId(), sortingReviewDto.getUserName(),
sortingReviewDto.getProfileImage(), sortingReviewDto.getImage(), sortingReviewDto.getRating(), tagDtos,
sortingReviewDto.getContent(), sortingReviewDto.isRebuy(), sortingReviewDto.getFavoriteCount(),
sortingReviewDto.isFavorite(), sortingReviewDto.getCreatedAt());
}

private static List<TagDto> findTagDtos(final Review review) {
return review.getReviewTags().stream()
.map(ReviewTag::getTag)
.map(TagDto::toDto)
.collect(Collectors.toList());
}

private static boolean findReviewFavoriteChecked(final Review review, final Member member) {
return review.getReviewFavorites()
.stream()
.filter(reviewFavorite -> reviewFavorite.getReview().equals(review))
.filter(reviewFavorite -> reviewFavorite.getMember().equals(member))
.findFirst()
.map(ReviewFavorite::getFavorite)
.orElse(false);
}

public Long getId() {
return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@

import java.time.LocalDateTime;

public class TestSortingReviewDto {
public class SortingReviewDtoWithoutTag {

private Long id;
private String userName;
private String profileImage;
private String image;
private Long rating;
private String content;
private Boolean rebuy;
private Long favoriteCount;
private Boolean favorite;
private LocalDateTime createdAt;
private final String userName;
private final String profileImage;
private final String image;
private final Long rating;
private final String content;
private final Boolean rebuy;
private final Long favoriteCount;
private final Boolean favorite;
private final LocalDateTime createdAt;

public TestSortingReviewDto(final Long id, final String userName, final String profileImage, final String image,
final Long rating, final String content,
final Boolean rebuy, final Long favoriteCount, final Boolean favorite,
final LocalDateTime createdAt) {
public SortingReviewDtoWithoutTag(final Long id, final String userName, final String profileImage,
final String image, final Long rating,
final String content, final Boolean rebuy, final Long favoriteCount,
final Boolean favorite,
final LocalDateTime createdAt) {
this.id = id;
this.userName = userName;
this.profileImage = profileImage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import com.funeat.member.domain.Member;
import com.funeat.review.domain.Review;
import com.funeat.review.dto.TestSortingReviewDto;
import com.funeat.review.dto.SortingReviewDtoWithoutTag;
import java.util.List;
import org.springframework.data.jpa.domain.Specification;

public interface ReviewCustomRepository {

List<TestSortingReviewDto> getSortingReview(final Member loginMember,
final Specification<Review> specification,
final String sortField);
List<SortingReviewDtoWithoutTag> getSortingReview(final Member loginMember,
final Specification<Review> specification,
final String sortField);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.funeat.member.domain.Member;
import com.funeat.member.domain.favorite.ReviewFavorite;
import com.funeat.review.domain.Review;
import com.funeat.review.dto.TestSortingReviewDto;
import com.funeat.review.dto.SortingReviewDtoWithoutTag;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
Expand All @@ -26,11 +26,11 @@ public class ReviewRepositoryImpl implements ReviewCustomRepository {
private EntityManager em;

@Override
public List<TestSortingReviewDto> getSortingReview(final Member loginMember,
final Specification<Review> specification,
final String sortOption) {
public List<SortingReviewDtoWithoutTag> getSortingReview(final Member loginMember,
final Specification<Review> specification,
final String sortOption) {
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<TestSortingReviewDto> cq = cb.createQuery(TestSortingReviewDto.class);
final CriteriaQuery<SortingReviewDtoWithoutTag> cq = cb.createQuery(SortingReviewDtoWithoutTag.class);
final Root<Review> root = cq.from(Review.class);

// sortField, sortOrder
Expand All @@ -52,19 +52,19 @@ public List<TestSortingReviewDto> getSortingReview(final Member loginMember,
.orderBy(getOrderBy(root, cb, sortField, sortOrder));

// limit
final TypedQuery<TestSortingReviewDto> query = em.createQuery(cq);
final TypedQuery<SortingReviewDtoWithoutTag> query = em.createQuery(cq);
query.setMaxResults(11);

// result
return query.getResultList();
}

private CompoundSelection<TestSortingReviewDto> getConstruct(final Root<Review> root,
final CriteriaBuilder cb,
final Join<Review, Member> joinMember,
final Join<Review, ReviewFavorite> leftJoinReviewFavorite) {
private CompoundSelection<SortingReviewDtoWithoutTag> getConstruct(final Root<Review> root,
final CriteriaBuilder cb,
final Join<Review, Member> joinMember,
final Join<Review, ReviewFavorite> leftJoinReviewFavorite) {

return cb.construct(TestSortingReviewDto.class,
return cb.construct(SortingReviewDtoWithoutTag.class,
root.get("id"),
joinMember.get("nickname"),
joinMember.get("profileImage"),
Expand Down

0 comments on commit e72b3d0

Please sign in to comment.