Skip to content

Commit

Permalink
[Feature/depromeet#118] UserService Querydsl 변경 (depromeet#92)
Browse files Browse the repository at this point in the history
* [fix] review -> feed 네이밍 변경

* [fix] review -> feed 네이밍 변경

* [refactor] 연관관계 끊기

* [refactor] 연관관계 끊기

* [refactor] feed-existBy- querydsl 변경

* [refactor] feed-findByUser querydsl 변경

* [refactor] bookmark-findByUser querydsl 변경

* [refactor] user-existsBy querydsl 변경

* [refactor] user,bookmark response 변경

* [refactor] TODO: 쿼리 최적화
  • Loading branch information
Ryuhyis authored Mar 12, 2024
1 parent a6c54a4 commit d5fb9ad
Show file tree
Hide file tree
Showing 15 changed files with 167 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import java.util.Optional;
import java.util.stream.Collectors;

import com.depromeet.domains.store.controller.KakaoSearchClient;
import com.depromeet.enums.CategoryType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.depromeet.domains.store.controller.KakaoSearchClient;
import com.depromeet.domains.store.dto.response.StoreSearchResponse;
import com.depromeet.domains.store.dto.response.StoreSearchResult;
import com.depromeet.domains.store.entity.Store;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import com.depromeet.domains.feed.entity.Feed;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -25,20 +22,17 @@
import com.depromeet.domains.feed.repository.FeedRepository;
import com.depromeet.domains.store.dto.request.FeedRequest;
import com.depromeet.domains.store.dto.request.NewStoreRequest;
import com.depromeet.domains.store.dto.response.FeedAddResponse;
import com.depromeet.domains.store.dto.response.FeedAddLimitResponse;
import com.depromeet.domains.store.dto.response.FeedAddResponse;
import com.depromeet.domains.store.dto.response.StoreFeedResponse;
import com.depromeet.domains.store.dto.response.StoreLocationRangeResponse;
import com.depromeet.domains.store.dto.response.StorePreviewResponse;
import com.depromeet.domains.store.dto.response.StoreReportResponse;
import com.depromeet.domains.store.dto.response.StoreFeedResponse;
import com.depromeet.domains.store.dto.response.StoreSharingSpotResponse;
import com.depromeet.domains.store.entity.Store;
import com.depromeet.domains.store.repository.StoreRepository;
import com.depromeet.domains.user.entity.User;
import com.depromeet.domains.user.repository.UserRepository;
import com.depromeet.enums.ReviewType;
import com.depromeet.enums.CategoryType;
import com.depromeet.enums.FeedType;
import com.depromeet.enums.UserLevel;
import com.depromeet.enums.ViewLevel;

Expand All @@ -61,7 +55,7 @@ public class StoreService {
public StorePreviewResponse getStore(Long storeId, User user) {

Store store = storeRepository.findById(storeId).orElseThrow(() -> new CustomException(Result.NOT_FOUND_STORE));
List<String > feedImageUrls = feedRepository.findTop10FeedImagesByCreatedAtDesc(store.getStoreId());
List<String> feedImageUrls = feedRepository.findTop10FeedImagesByCreatedAtDesc(store.getStoreId());

Boolean isBookmarked = false;
if (bookmarkRepository.findByUserAndStore(user, store).isPresent()) {
Expand All @@ -88,21 +82,22 @@ public StoreReportResponse getStoreReport(Long storeId) {
return StoreReportResponse.of(
store.getStoreId(),
store.getThumbnailUrl(),
null, null);
null, null);
}

// 음식점 리뷰 조회(타입별 조회)
@Transactional(readOnly = true)
public Slice<StoreFeedResponse> getStoreFeed(User user, Long storeId,
Pageable pageable) {
Pageable pageable) {

Store store = storeRepository.findById(storeId).orElseThrow(() -> new CustomException(Result.NOT_FOUND_STORE));

Integer size = 10;
Sort sort = Sort.by(Sort.Direction.DESC, "createAt");
PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), size, sort);

Slice<StoreFeedResponse> feeds = feedRepository.findFeedByStoreId(storeId, (PageRequest) pageable, user.getUserId());
Slice<StoreFeedResponse> feeds = feedRepository.findFeedByStoreId(storeId, (PageRequest)pageable,
user.getUserId());
// Review 객체를 StoreLogResponse DTO로 변환하여 Slice 객체에 담아 반환
return feeds;
}
Expand All @@ -128,8 +123,8 @@ public StoreLocationRangeResponse getRangeStores(Double leftTopLatitude, Double
ViewLevel viewLevel = ViewLevel.findByLevel(level);

List<Store> storeListWithCondition
= this.storeRepository.findByLocationRangesNotInBookmarks(maxLatitude,
minLatitude, maxLongitude, minLongitude, bookMarkStoreIdList);
= this.storeRepository.findByLocationRangesNotInBookmarks(maxLatitude,
minLatitude, maxLongitude, minLongitude, bookMarkStoreIdList);

int viewStoreListCount = calculateViewStoreListRatio(storeListWithCondition.size(), viewLevel);

Expand Down Expand Up @@ -237,7 +232,8 @@ private Store updateStoreInfo(FeedRequest feedRequest) {

// 평점과 리뷰 개수 업데이트
store.updateTotalRating(feedRequest.getRating());
store.increaseTotalFeedCnt();;
store.increaseTotalFeedCnt();
;
return store;
}

Expand All @@ -250,7 +246,6 @@ private Store createNewStore(FeedRequest feedRequest) {
return storeRepository.save(newStore.toEntity(feedRequest.getRating(), feedRequest.getImageUrl()));
}


private Feed saveFeed(Feed feed) {
return feedRepository.save(feed);
}
Expand Down Expand Up @@ -357,7 +352,8 @@ public FeedAddLimitResponse checkUserDailyStoreFeedLimit(User user, Long storeId
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59);

Long feedCount = feedRepository.countStoreReviewByUserForDay(user.getUserId(), store.getStoreId(), startOfDay, endOfDay);
Long feedCount = feedRepository.countStoreReviewByUserForDay(user.getUserId(), store.getStoreId(), startOfDay,
endOfDay);
return FeedAddLimitResponse.of(feedCount < 3);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import com.depromeet.domains.user.dto.request.NicknameRequest;
import com.depromeet.domains.user.dto.response.UserBookmarkResponse;
import com.depromeet.domains.user.dto.response.UserProfileResponse;
import com.depromeet.domains.user.dto.response.UserReviewResponse;
import com.depromeet.domains.user.dto.response.UserFeedResponse;
import com.depromeet.domains.user.entity.User;
import com.depromeet.domains.user.service.UserService;

Expand Down Expand Up @@ -56,9 +56,9 @@ public CustomResponseEntity<Slice<UserBookmarkResponse>> getMyBookmarks(@AuthUse
/**
* 내 리뷰 반환
*/
@GetMapping("/reviews")
public CustomResponseEntity<Slice<UserReviewResponse>> getMyReviews(@AuthUser User user, Pageable pageable) {
return CustomResponseEntity.success(userService.getUserReviews(user, pageable));
@GetMapping("/feeds")
public CustomResponseEntity<Slice<UserFeedResponse>> getMyFeeds(@AuthUser User user, Pageable pageable) {
return CustomResponseEntity.success(userService.getUserFeeds(user, pageable));
}

@DeleteMapping("/withdraw")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,17 @@ public class UserBookmarkResponse {
private String storeName; // 북마크한 가게 이름
private String address; // 북마크한 가게 주소
private Long totalRevisitedCount; // 북마크한 가게에 총 몇명이 재방문했는지
private String categoryName; // 북마크한 가게의 카테고리
private String kakaoCategoryName; // 북마크한 가게의 카테고리
private Boolean isVisited; // 북마크한 가게에 내가 방문했는지 안했는지

public static UserBookmarkResponse of(Long bookmarkId, Long storeId, String storeName, String address, Long totalRevisitedCount,
String categoryName, Boolean isVisited) {
public static UserBookmarkResponse of(Long bookmarkId, Long storeId, String storeName, String address,
String kakaoCategoryName, Boolean isVisited) {
return UserBookmarkResponse.builder()
.bookmarkId(bookmarkId)
.storeId(storeId)
.storeName(storeName)
.address(address)
.totalRevisitedCount(totalRevisitedCount)
.categoryName(categoryName)
.kakaoCategoryName(kakaoCategoryName)
.isVisited(isVisited)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.depromeet.domains.user.dto.response;

import java.time.LocalDate;
import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonFormat;

Expand All @@ -9,27 +9,25 @@

@Getter
@Builder
public class UserReviewResponse {
private Long reviewId;
public class UserFeedResponse {
private Long feedId;
private Long storeId;
private String storeName;
private Integer visitTimes;
@JsonFormat(pattern = "yyyy.MM.dd")
private LocalDate visitedAt;
private LocalDateTime createdAt;
private String categoryName;
private Integer rating;
private String imageUrl;
private String description;

public static UserReviewResponse of(Long reviewId, Long storeId, String storeName, Integer visitTimes, LocalDate visitedAt,
public static UserFeedResponse of(Long feedId, Long storeId, String storeName, LocalDateTime createdAt,
String categoryName,
Integer rating, String imageUrl, String description) {
return UserReviewResponse.builder()
.reviewId(reviewId)
return UserFeedResponse.builder()
.feedId(feedId)
.storeId(storeId)
.storeName(storeName)
.visitTimes(visitTimes)
.visitedAt(visitedAt)
.createdAt(createdAt)
.categoryName(categoryName)
.rating(rating)
.imageUrl(imageUrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import com.depromeet.common.exception.Result;
import com.depromeet.domains.bookmark.entity.Bookmark;
import com.depromeet.domains.bookmark.repository.BookmarkRepository;
import com.depromeet.domains.feed.entity.Feed;
import com.depromeet.domains.feed.repository.FeedRepository;
import com.depromeet.domains.store.entity.Store;
import com.depromeet.domains.store.repository.StoreRepository;
import com.depromeet.domains.user.dto.response.UserBookmarkResponse;
import com.depromeet.domains.user.dto.response.UserProfileResponse;
import com.depromeet.domains.user.dto.response.UserReviewResponse;
import com.depromeet.domains.user.dto.response.UserFeedResponse;
import com.depromeet.domains.user.entity.User;
import com.depromeet.domains.user.repository.UserRepository;

Expand All @@ -29,6 +31,7 @@ public class UserService {
private final UserRepository userRepository;
private final BookmarkRepository bookmarkRepository;
private final FeedRepository feedRepository;
private final StoreRepository storeRepository;

@Transactional
public void updateUserNickname(User user, String nickname) {
Expand All @@ -48,26 +51,27 @@ public UserProfileResponse getUserProfile(User user) {
@Transactional(readOnly = true)
public Slice<UserBookmarkResponse> getUserBookmarks(User user, Pageable pageable) {
PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(Sort.Direction.DESC, "createdAt"));
Slice<Bookmark> bookmarks = bookmarkRepository.findByUser(user, pageRequest);

Slice<Bookmark> bookmarks = bookmarkRepository.findByUserId(user.getUserId(), pageRequest);
// TODO : 쿼리 최적화 (store 정보를 한번에 가져오기)
List<UserBookmarkResponse> userBookmarkResponses = bookmarks.stream()
.map(this::getUserBookemarkResponse)
.map(this::getUserBookmarkResponse)
.collect(Collectors.toList());

return new SliceImpl<>(userBookmarkResponses, bookmarks.getPageable(), bookmarks.hasNext());
}

@Transactional(readOnly = true)
public Slice<UserReviewResponse> getUserReviews(User user, Pageable pageable) {
public Slice<UserFeedResponse> getUserFeeds(User user, Pageable pageable) {

PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(Sort.Direction.DESC, "visitedAt"));
Slice<Review> reviews = feedRepository.findByUser(user, pageRequest);
Slice<Feed> feeds = feedRepository.findByUserId(user.getUserId(), pageRequest);

List<UserReviewResponse> userReviewResponses = reviews.stream()
.map(this::getUserReviewResponse)
// TODO : 쿼리 최적화 (store 정보를 한번에 가져오기)
List<UserFeedResponse> userFeedResponses = feeds.stream()
.map(this::getUserFeedResponse)
.collect(Collectors.toList());

return new SliceImpl<>(userReviewResponses, reviews.getPageable(), reviews.hasNext());
return new SliceImpl<>(userFeedResponses, feeds.getPageable(), feeds.hasNext());
}

private User findUserById(Long userId) {
Expand All @@ -84,32 +88,35 @@ private Pageable getPageable(Pageable pageable, String sortBy) {
return PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(Sort.Direction.DESC, sortBy));
}

private UserBookmarkResponse getUserBookemarkResponse(Bookmark bookmark) {
Store store = bookmark.getStore();
boolean isVisited = feedRepository.existsByStoreAndUser(store, bookmark.getUser());
private UserBookmarkResponse getUserBookmarkResponse(Bookmark bookmark) {
Store store = storeRepository.findById(bookmark.getBookmarkId())
.orElseThrow(() -> new CustomException(Result.NOT_FOUND_STORE));

boolean isVisited = feedRepository.existsByStoreAndUser(bookmark.getStoreId(), bookmark.getUserId());

return UserBookmarkResponse.of(
bookmark.getBookmarkId(),
store.getStoreId(),
store.getStoreName(),
store.getAddress(),
store.getStoreMeta().getTotalRevisitedCount(),
store.getCategory().getCategoryName(),
store.getKakaoCategoryName(),
isVisited
);
}

private UserReviewResponse getUserReviewResponse(Review review) {
return UserReviewResponse.of(
review.getReviewId(),
review.getStore().getStoreId(),
review.getStore().getStoreName(),
review.getVisitTimes(),
review.getVisitedAt(),
review.getStore().getCategory().getCategoryName(),
review.getRating(),
review.getImageUrl(),
review.getDescription()
private UserFeedResponse getUserFeedResponse(Feed feed) {
Store store = storeRepository.findById(feed.getStoreId())
.orElseThrow(() -> new CustomException(Result.NOT_FOUND_STORE));

return UserFeedResponse.of(
feed.getFeedId(),
store.getStoreId(),
store.getStoreName(),
feed.getCreatedAt(),
store.getKakaoCategoryName(),
feed.getRating(),
feed.getImageUrl(),
feed.getDescription()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.depromeet.domains.user.dto.request.NicknameRequest;
import com.depromeet.domains.user.dto.response.UserBookmarkResponse;
import com.depromeet.domains.user.dto.response.UserProfileResponse;
import com.depromeet.domains.user.dto.response.UserReviewResponse;
import com.depromeet.domains.user.dto.response.UserFeedResponse;

@AutoConfigureMockMvc
@AutoConfigureRestDocs
Expand Down Expand Up @@ -180,7 +180,7 @@ void getMyBookmarks() throws Exception {
@Test
void getMyReviews() throws Exception {
// given
UserReviewResponse userReviewResponse1 = UserReviewResponse.builder()
UserFeedResponse userReviewResponse1 = UserFeedResponse.builder()
.reviewId(1L)
.storeId(1L)
.storeName("칠기마라탕")
Expand All @@ -192,7 +192,7 @@ void getMyReviews() throws Exception {
.description("맛있어요")
.build();

UserReviewResponse userReviewResponse2 = UserReviewResponse.builder()
UserFeedResponse userReviewResponse2 = UserFeedResponse.builder()
.reviewId(2L)
.storeId(1L)
.storeName("칠기마라탕")
Expand All @@ -204,7 +204,7 @@ void getMyReviews() throws Exception {
.description("맛있어요")
.build();

UserReviewResponse userReviewResponse3 = UserReviewResponse.builder()
UserFeedResponse userReviewResponse3 = UserFeedResponse.builder()
.reviewId(3L)
.storeId(2L)
.storeName("알베르")
Expand All @@ -216,8 +216,8 @@ void getMyReviews() throws Exception {
.description("맛있어요")
.build();

List<UserReviewResponse> content = Arrays.asList(userReviewResponse1, userReviewResponse2, userReviewResponse3);
Slice<UserReviewResponse> userReviewResponses = new SliceImpl<>(content, Pageable.unpaged(), true);
List<UserFeedResponse> content = Arrays.asList(userReviewResponse1, userReviewResponse2, userReviewResponse3);
Slice<UserFeedResponse> userReviewResponses = new SliceImpl<>(content, Pageable.unpaged(), true);

given(userService.getUserReviews(any(), any())).willReturn(userReviewResponses);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
package com.depromeet.domains.bookmark.repository;

import com.depromeet.domains.store.entity.Store;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.depromeet.domains.bookmark.entity.Bookmark;
import com.depromeet.domains.store.entity.Store;
import com.depromeet.domains.user.entity.User;

import java.util.List;
import java.util.Optional;

public interface BookmarkRepository extends JpaRepository<Bookmark, Long>, BookmarkRepositoryCustom {

Slice<Bookmark> findByUser(User user, Pageable pageable);

Optional<Bookmark> findByUserAndStore(User user, Store store);

List<Bookmark> findByUserId(Long userId);
Expand Down
Loading

0 comments on commit d5fb9ad

Please sign in to comment.